views:

308

answers:

4

I have a really weird issue that I can't figure out with comparing objects on IIS 7. We are in the process of deploying our old IIS 6 based ASP.NET application on IIS 7, however we have this equality comparison issue that we can't seem to figure out.

Let me start out by saying that I have the same assemblies and code running both on IIS 6 and IIS 7, however the comparison of the objects is differing with the same code both on IIS 6 and IIS 7. Here is an example of what my object looks like:

class Country : EntityBase {
    public int CountryID { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj) {
        if (obj == null || !(obj is Country))
            return false;

        Country c = (Country)obj;
        return CountryID == c.CountryID;
    }

    public override int GetHashCode() {
        return CountryID.GetHashCode();
    }
}

I have the following code in an ASPX page both on IIS 6 and IIS 7:

<% foreach(var country in proposalCountries) { %>
<%= country.Country.CountryID %>
<%= country.Country.CountryID.GetHashCode() %>
<%= country.Country.GetHashCode() %>

<%= proposalCountryServices.Count(c => c.Country == country.Country) %>
<%= proposalCountryServices.Count(c => (c.Country != null && country.Country != null) && c.Country.Equals(country.Country)) %>)
<%= proposalCountryServices.Count(c => Object.Equals(c.Country, country.Country)) %>
<% } %>

Here are my results:

IIS 6:

100 <-- CountryID
100 <-- CountryID Hash Code
100 <-- Country Hash Code

1 <-- Something Found
1 <-- Something Found
1 <-- Something Found

IIS 7:

100 <-- CountryID
100 <-- CountryID Hash Code
100 <-- Country Hash Code

0 <-- Nothing Found
1 <-- Something Found
1 <-- Something Found

Is there a difference between .NET 3.5 SP1 on Windows 2003 vs Windows 2008? I am really at a loss of what the problem could be. Has anybody experienced a similar issue?

Update 1:

To answer Jon's question. The two collections are loaded using NHibernate. But I feel I should reiterate that both IIS 6 and IIS 7 are using the exact same build of the application, so unless NHibernate or DynamicProxy2 is changing how things are loaded based on Windows 2003 or Windows 2007, which I haven't been able to find anything about on Google, I don't know what to make of it.

This is also a system wide issue of whenever I am comparing two of my entity objects. So it could have something to do with the DynamicProxy2 wrapper, but both objects are Country objects and given the overrides I have created everything should work the same in IIS 6 and IIS 7.

Update 2:

This appears to be a DynamicProxy2 or NHibernate issue. Because I tried the following code:

<%
    var c1 = new ICost.Business.Entities.Country {
     CountryID = 100
    };
    var c2 = new ICost.Business.Entities.Country {
     CountryID = 100
    };
%>
<%= c1.CountryID == c2.CountryID %>
<%= c1.GetHashCode() == c2.GetHashCode() %>
<%= c1.Equals(c2) %>
<%= Object.Equals(c1, c2) %>
<%= c1 == c2 %>

And for both IIS 6 and IIS 7 the result was, true, true, true, true, false. See my answer below for what I did to solve this.

Update 3:

This also might have had something to do with it: http://stackoverflow.com/questions/258011/problem-with-windsor-castle-with-iis7

A: 

the difference I see is in case one you wrote

c.Country == country.Country

and in case two it is

c.Country.Equals(country.Country))

so I'd guess that in the latter case he succeeds because he is comparing the CountryIDs of both objects in the first case however he is comparing the objects themself.

Why this works under IE6 I don't know... sorry

Gambrinus
Hi Gambrinus, it is IIS 6, not IE 6. Also I see the difference, but there shouldn't be any difference given the two systems and how they handle objects.
Nick Berardi
A: 

You are not using referential equality (see below).

Object.Equals will call an overridden Equals method on your type.

I suspect you have pulled out different instances of the entities from different DataContexts, and added it to a list, and hence using an overriden Equals to try make it work.

Update:

Sorry, not sure if you are using LINQ2SQL.

You could probably fix the issue by overriding the ==/!= operators, but there are some considerations to take with that too.

Update 2:

To understand what I mean, find both instances you deem to be equal (exactly where this issue happens). Set a breakpoint. Now, go &obj1 and enter and &obj2 and enter, you will notice they point to different object addresses. Do this on both IIS 6 and 7.

I am not sure why it is behaving differently on IIS6 and IIS7, but I suspect subtle differences in the page lifecycle could be the cause why they are not referentially equal.

Update 3:

Are you running under classic mode in IIS7? If not, try doing so.

leppie
But I think you are missing the point. If that was the case both systems should be working differently. They are both using the same code, database, etc. and the three tests I did were all testing the same collection.
Nick Berardi
I am not using LINQ2SQL it is actually NHibernate. I don't really want to override the ==/!= operators because this issue is popping up all over the system, not on just this one object.
Nick Berardi
No, the cases are different, i'll expand the answer.
leppie
Nope both objects are different on IIS 6 and IIS 7. I already checked this, and that is why I overrode the GetHashCode so they would be compared as the same.
Nick Berardi
But overriding GetHashCode has no effect on equality...
leppie
If you dont override == , its the same as ReferenceEquals
leppie
Intigrated pipeline, I will give it a try, but this is at the core of .NET and shouldn't be effected by the runtime.
Nick Berardi
I think that might be the problem :) If it is, it think I know why. Probably the NHibernate Session Module IIRC (I last used NHibernate 3 years back).
leppie
+1  A: 

You haven't explained what proposalCountries and proposalCountryServices are. It looks to me like your Equals method is working just fine, but in IIS7 they contain distinct objects - you've got two objects with the same ID (so Equals matches) but they're distinct objects, so == doesn't match.

Please give details as to how the two collections are loaded - that's likely to be the cause of it.

Jon Skeet
proposalCountries and proposalCountryServices are just collections of objects that contain Country as a property. This is just an example of one thing that isn't working, but this seems to be appearing all over the system with different objects not related to Country. Still doesn't explain IIS 6
Nick Berardi
The two collections are loaded using NHibernate. But both IIS 6 and IIS 7 are using the exact same build of the application, so unless NHibernate or DynamicProxy2 is changing how things are loaded based on Windows 2003 or Windows 2007 I don't know what to make of it.
Nick Berardi
A: 

This is the solution that worked for me:

public static bool operator ==(BaseEntity a, BaseEntity b)
{
    return Object.Equals(a, b);
}

public static bool operator !=(BaseEntity a, BaseEntity b)
{
    return !Object.Equals(a, b);
}

Apparently NHibernate or DynamicProxy was doing some kind of magic under Windows 2003 to get the "==" operator to work with out the operator being overloaded.

Nick Berardi