tags:

views:

41

answers:

3

I am having difficulties following all of the rules for the GetHashCode method in MSDN for a class whose only property is a Connection String.

I have tried just returning the hash of the string, but that returns a different value for the strings Provider=Microsoft.ACE.OLEDB.12.0; Data Source=path, Provider=Microsoft.ACE.OLEDB.12.0; Data Source=path; and Data Source=path;Provider=Microsoft.ACE.OLEDB.12.0;, all of which are equivalent.

Then, I tried using the OleDbConnectionStringBuilder.GetHashCode method, but that doesn't even return the same HashCode in this case:

test1.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" +
        PathToExcelFile + ";Extended Properties='Excel 12.0 Macro;HDR=YES;IMEX=1';";
test2.ConnectionString = test1.ConnectionString;

Console.WriteLine(test1.GetHashCode());
Console.WriteLine(test2.GetHashCode());

My goal is to use my class as a Key to a Dictionary, so GetHashCode is kind of important. How should I go about implementing it?

+2  A: 

Define a canonical connection string and call GetHashCode on that string. In this case, you could define "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=path" as your canonical form, and then you would need to transform all equivalent connection strings to the canonical string and then call GetHashCode.

The question then becomes: How hard is it to turn all equivalent connection strings into the same string?

Joel Rondeau
A: 

It's very difficult, if not impossible, to determine if connectionstrings are equal. The only assumption you can make is that if the strings are equal, the connection strings are.

For example - "." might be equal to "localhost". Or localhost might have a hosts file entry redefining it.. Some future version of the framework might require a ";" at the end of the string.. two driver versions might be functionally equivalent but you treat them differently.. where you draw the line is a very flaky matter.

My point: Unless you use a class that defines each specific component of the connection string, you have no business deciding whether two connection strings are equal, beyond comparing the strings.

Kieren Johnstone
A: 

I've solved this problem based on input from both answers:

Define a canonical connection string

And

Unless you use a class that defines each specific component of the connection string, you have no business deciding whether two connection strings are equal, beyond comparing the strings.

So, I created an extension method to OleDbConnectionStringBuilder:

public static int GetRealHashCode(this OleDbConnectionStringBuilder target)
{
    int ToReturn = 17;
    ToReturn *= target.DataSource.TrimEnd(';').GetHashCode();
    ToReturn *= target.Provider.TrimEnd(';').GetHashCode();
    ToReturn *= target.PersistSecurityInfo.ToString().GetHashCode();

    var OrderedKeys = from string key in target.Keys
              orderby key
              select key;
    foreach (string Key in OrderedKeys)
        ToReturn *= target[Key].GetHashCode();

    return ToReturn;
}
DonaldRay