Monday, February 2, 2015

Entity framework 5 can't connect to Oracle DB in Windows 2012 server

Recently I did a project using Entity Framework 5 with Oracle DB.
Only Entity framework 5 is able to connect to Oracle, I'm using Oracle 12c so must use the ODAC 12.10.1.2 for coding.
When running in local, it's working fine.
However when deploying to the server, I encountered this error:

ORA-12504: TNS:listener was not given the SERVICE_NAME in CONNECT_DATA

Reinstalling ODAC doesn't work.
All TNS was updated in tnsnames.ora.
However it seems EF can't locate the TNS in tnsnames.ora.

Changing the connection string to be same like the one in tnsnames.ora doesn't work.

metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string='Data Source=MYDB.WORLD;USER ID=XXX;PASSWORD=YYY;'

After enough searching here and there.. I found a temporary solution, that is to embed the TNS names in the connection string itself.

So my entity framework connection string is now like below:

metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string='Data Source=(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = MYDBSERVER)(PORT = 1111))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = MYDB)));USER ID=XXX;PASSWORD=YYY;'

Reference : http://nullablecode.com/2013/10/ef-oracle-db-connection-problem-ora-12504/

Tuesday, November 19, 2013

System.BadImageFormatException: Could not load file or assembly 'xxx.dll'or one of its dependencies. An attempt was made to load a program with an incorrect format.

If you encounter below error when running Visual Studio .NET but compilation is successful.
System.BadImageFormatException: Could not load file or assembly 'xxx.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Resolution:
1) Ensure that all projects have the same .net framework version you can check this from each project properties.
2) Ensure that the target platform is Any CPU on solution properties and each project properties (for .NET it's under Compile section, for C# it's under Build section).

Reference: here

Tuesday, October 8, 2013

Windows 7 upgrade error - External table is not in the expected format.

Before the upgrade it's working fine, after upgrade, my user experienced that error:
External table is not in the expected format.

After debugging, found out that there's 2 files being processed, even though my user only puts 1 file into the upload folder.
Turned out to be the second file is Thumbs.db, usually used for thumbnails.
But I cannot see this file in the folder itself.
So what do we need to do?
Simple, just ask your user to go to Windows Explorer, go to Tools, Folder Options

On View tab, tick the first one, Always show icons, never thumbnails then click ok.
Go to that upload folder, remove any Thumbs.db if there's is any.
It should solve the problem.

Reference: here

Thursday, September 26, 2013

Cleaning COM Objects when coding using Interop.Excel

Proper coding with releasing of the COM objects must be done when coding to create excel reports using Microsoft.Office.Interop.Excel in order to avoid memory leak.

Please refer to this example to automate excel with proper releasing of COM objects in VS2010.
In the example, Solution1.AutomateExcel demonstrates automating Microsoft Excel application by using Microsoft Excel Primary Interop Assembly (PIA) and explicitly assigning each COM accessor object to a new variable that you would explicitly call Marshal.FinalReleaseComObject to release it at the end. When you use this solution, it is important to avoid calls that tunnel into the object model because they will orphan Runtime Callable Wrapper (RCW) on the heap that you will not be able to access in order to call Marshal.ReleaseComObject. You need to be very careful. For example,

  Excel.Workbook oWB = oXL.Workbooks.Add(missing);

Calling oXL.Workbooks.Add creates an RCW for the Workbooks object. If you invoke these accessors via tunneling as this code does, the RCW for Workbooks is created on the GC heap, but the reference is created under the hood on the stack and are then discarded. As such, there is no way to call MarshalFinalReleaseComObject on this RCW. To get such kind of RCWs released, you would either need to force a garbage collection as soon as the calling function is off the stack (see Solution2.AutomateExcel), or you would need to explicitly assign each accessor object to a variable and free it.

  Excel.Workbooks oWBs = oXL.Workbooks;
  Excel.Workbook oWB = oWBs.Add(missing);

In the example, Solution2.AutomateExcel demonstrates automating Microsoft Excel application by using Microsoft Excel Primary Interop Assembly (PIA) and forcing a garbage collection as soon as the automation function is off the stack (at which point the Runtime Callable Wrapper (RCW) objects are no longer rooted) to clean up RCWs and release COM objects.

public static void AutomateExcel()
        {
            AutomateExcelImpl();


            // Clean up the unmanaged Excel COM resources by forcing a garbage
            // collection as soon as the calling function is off the stack (at
            // which point these objects are no longer rooted).

            GC.Collect();
            GC.WaitForPendingFinalizers();
            // GC needs to be called twice in order to get the Finalizers called
            // - the first time in, it simply makes a list of what is to be
            // finalized, the second time in, it actually is finalizing. Only
            // then will the object do its automatic ReleaseComObject.
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

Read more on the Marshal.ReleaseCOMObjects is dangerous to be used here.

Wednesday, September 18, 2013

Sharepoint WS - List - Delete file

here is the code to delete a file.
Note that FileRef cannot use encoded URL.
For the GetDocID method can refer to this post.

 private static void DeleteFile(string FilePath)  
     {  
       try  
       {  
         using (ListWS.Lists listService = new ListWS.Lists())  
         {  
           listService.Url = ListURL;  
           listService.Credentials = System.Net.CredentialCache.DefaultCredentials;  
           listService.Credentials = new System.Net.NetworkCredential(username, password);  
           //Get the file id  
           string fileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);  
           string DocID = GetDocID(fileName);  
           //get guid  
           string lListName = "EDMS";  
           XmlNode lSharePointListName = listService.GetList(lListName);  
           string lListID = lSharePointListName.Attributes["ID"].Value;   
           XmlDocument doc = new XmlDocument();  
           //Perform deletion  
           string xmlCommand;  
           doc = new XmlDocument();  
           //ID is the ID field value of MyFolder element  
           xmlCommand = "<Method ID='1' Cmd='Delete'><Field Name='ID'>" + DocID + "</Field><Field Name='FileRef'>" +   
             FilePath.Replace("%20"," ") + "</Field></Method>";  
           XmlElement ele = doc.CreateElement("Batch");  
           ele.SetAttribute("OnError", "Continue");  
           ele.SetAttribute("ListVersion", "1");  
           //ele.SetAttribute("RootFolder", FilePath.Substring(0, FilePath.LastIndexOf("/")));  
           ele.InnerXml = xmlCommand;  
           XmlNode node1 = listService.UpdateListItems(lListID, ele);  
           if ((node1 != null) && (node1.InnerText == SUCCESS))  
           {  
             Console.WriteLine("SUCCESS");  
           }  
           else  
           {  
             Console.WriteLine("There is an error : " + node1.InnerText);  
           }  
         }  
       }  
       catch (Exception ex)  
       {  
         throw ex;  
       }  
     }  

here is the error that you may get:
1) 0x81020030Invalid file name.\n\nThe file name you specified could not be used. It may be the name of an existing file or directory, or you may not have permission to access the file.
This is because FileRef must be included in the query for deleting the item.

2) You got success code (0x00000000) however the file just stays there in the Document Library.
This is because the FileRef path is using encoded URL
(eg. http://url/a/b/c/cc%20c.pdf -> must change to -> http://url/a/b/c/cc c.pdf)
After changing to non-encoded URL, wala.. it's working like magic!

Hope it helps!

Sharepoint WS References

Good reference websites:
http://sarangasl.blogspot.sg/2009/12/addupdate-list-item-using-sharepoint.html
http://sarangasl.blogspot.sg/2009/12/sharepoint-list-web-service.html
http://sarangasl.blogspot.sg/2009/10/caml-spquery-in-sharepoint.html

CAML Query Helper to help you create the query, can just download, it's quite easy to use.
http://spcamlqueryhelper.codeplex.com/

Sharepoint WS - Copy - Move the file from one server to another

Here's the method
faxObj is just an object if u wan to include for the field information purpose.
EDMSPath is the source
EDMSRPath is the destination

 private static bool MoveEDMSToEDMSR(ISDAFaxDBO faxObj, string EDMSPath, string EDMSRPath, string msg ="")  
     {  
       using (CopyWS.Copy copyService = new CopyWS.Copy())  
       {  
         copyService.Url = CopyURL;  
         copyService.Credentials = System.Net.CredentialCache.DefaultCredentials;  
         copyService.Credentials = new System.Net.NetworkCredential(username, password);  
         CopyWS.FieldInformation fiEDMS = new CopyWS.FieldInformation();  
         CopyWS.FieldInformation[] fi = { fiEDMS };  
         byte[] byteArr;  
         uint getFile = copyService.GetItem(EDMSPath, out fi, out byteArr);  
         string[] destination = { EDMSRPath };  
         CopyWS.CopyResult cResult1 = new CopyWS.CopyResult();  
         CopyWS.CopyResult cResult2 = new CopyWS.CopyResult();  
         CopyWS.CopyResult[] cResultArray = { cResult1, cResult2 };  
         CopyWS.FieldInformation fiRecordDate = new CopyWS.FieldInformation();  
         fiRecordDate.DisplayName = "Record Date";  
         fiRecordDate.Type = CopyWS.FieldType.DateTime;  
         fiRecordDate.Value = faxObj.MaturityDate.ToString("yyyy/MM/ddT00:00:00Z");  
         CopyWS.FieldInformation fiSector = new CopyWS.FieldInformation();  
         fiSector.DisplayName = "Sector";  
         fiSector.Type = CopyWS.FieldType.Choice;  
         fiSector.Value = "Fax";  
         CopyWS.FieldInformation[] fis = { fiRecordDate, fiSector };  
         uint copyresult = copyService.CopyIntoItems(EDMSPath, destination, fis, byteArr, out cResultArray);  
         //Array.Resize<CopyWS.FieldInformation>(ref fi, fi.Length + 2);  
         //fi[fi.Length - 2] = fiRecordDate;  
         //fi[fi.Length - 1] = fiSector;  
         //uint copyresult = copyService.CopyIntoItems(EDMSPath, destination, fi, byteArr, out cResultArray);  
         if (copyresult == 0)  
         {  
           int idx = 0;  
           foreach (CopyWS.CopyResult myCopyResult in cResultArray)  
           {  
             string opString = (idx + 1).ToString();  
             if (cResultArray[idx].ErrorMessage == null)  
             {  
               msg += "Copy operation " + opString +  
                 "completed.\r\n" + "Destination: " +  
                 cResultArray[idx].DestinationUrl;  
             }  
             else  
             {  
               msg += "Copy operation " + opString +  
                 " failed.\r\n" + "Error: " +  
                 cResultArray[idx].ErrorMessage + "\r\n" +  
                 "Code: " + cResultArray[idx].ErrorCode;  
             }  
             idx++;  
           }  
           return true;  
         }  
         else  
         {  
           return false;  
         }  
       }  
     }