I Prefer Jim Developer James Schubert shares his code and his thoughts.

22Apr/10

DRY! GenericComparer for sorting Generic Lists

I'm a pretty firm believer in the Ruby/Ruby on Rails idea of DRY ("Don't Repeat Yourself").

That said, I get pretty tired of writing comparers for sorting lists and generic lists. Every one of these comparers is exactly the same: you specify a list of properties related to the object and a sort direction, then call compare on those properties.

This can be changed with a little reflection:

   public class GenericComparer<T> : IComparer<T>
    {
        public string SortExpression { get; set; }
        public int SortDirection { get; set; } // 0:Ascending, 1:Descending

        public GenericComparer(string sortExpression, int sortDirection)
        {
            this.SortExpression = sortExpression;
            this.SortDirection = sortDirection;
        }
        public GenericComparer() { }

        #region IComparer<T> Members
        public int Compare(T x, T y)
        {
            PropertyInfo propertyInfo = typeof(T).GetProperty(SortExpression);
            IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
            IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);

            if (SortDirection == 0)
            {
                return obj1.CompareTo(obj2);
            }
            else return obj2.CompareTo(obj1);
        }
        #endregion
    }

This is a code snippet I love to have in my arsenal.

Here's how you use it:

List<MyObject> objectList = GetObjects(); /* from your repository or whatever */
objectList.Sort(new GenericComparer<MyObject>("ObjectPropertyName", (int)SortDirection.Descending));
dropdown.DataSource = objectList;
dropdown.DataBind();

Note that Sort returns void. This means you can't throw this to the right of a DataSource call. You'd have to call this, then call your DataSource/DataBind.

Tagged as: , , No Comments
9Apr/10

Oracle Exception: Could not load file or assembly ‘Oracle.DataAccess, Version=2.111.7.20…

Last week, I was having performance issues with my workstation. I was told to remove unused files and applications. I had previously installed ODAC 11g for the Oracle Data Providers. After realizing they were not backwards compatible with the Oracle10g providers we're using in production, I removed ODAC 11g using the Oracle Universal Installer. Apparently, that doesn't completely remove references to the 11g client or components.

After removing files and directories, I began receiving the following error when accessing an application locally:

    Exception message: Could not load file or assembly 'Oracle.DataAccess, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

To see what Oracle libraries are installed in the GAC, I ran the following command from a Visual Studio command prompt:

gacutil /l | find /i "Oracle" > c:\Scripts\oracle.txt

This gave me the following list (note: Oracle 2.111.7.20 libraries are installed by ODAC 11g)

Oracle.DataAccess, Version=2.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86
  Oracle.Management.Omo, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86
  Oracle.VsDevTools, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86
  Oracle.Web, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86
  Policy.2.102.Oracle.DataAccess, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86
  System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86
  Oracle.DataAccess, Version=1.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342
  Oracle.DataAccess, Version=1.102.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342
  Oracle.Management.Omo, Version=1.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342
  Oracle.VsDevTools, Version=1.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342
  Policy.1.102.Oracle.DataAccess, Version=1.102.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342
  Policy.10.1.Oracle.DataAccess, Version=1.102.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342
  Policy.10.2.Oracle.DataAccess, Version=1.102.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342
  Policy.9.2.Oracle.DataAccess, Version=1.102.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342
  System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

I have spent a week trying to figure out why these libraries wouldn't uninstall from the GAC and why I couldn't possibly remove them from the Oracle Universal Installer.

To manually uninstall these libraries, you'll have to run the following commands from a Visual Studio Command Prompt:

gacutil /u "Oracle.Management.Omo, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86"
gacutil /u "Oracle.VsDevTools, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86"
gacutil /u "Oracle.Web, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86"
gacutil /u "Policy.2.102.Oracle.DataAccess, Version=2.111.7.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86"

Here's the part that got me: I installed ODT, not just ODAC. This comes with a number of add-ons for Visual Studio (including Health Monitoring and Profiling). So, you have to manually edit the machine.config to get everything completely removed.
So,
Edit C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config and remove all references from the above libraries.

After following these steps, I was finally able to load the application locally using the ODAC/ODP.NET libraries for Oracle 10g.