Derik Whittaker

Syndication

News


EF + Overriding Equals == Massive headache

Do you ever have one of those ‘Doh’ days?  One of those days where you spend like 6 hours trying to replicate a bug simply so you can debug it.  One of those days you wish you could have back?  Well I had one of those last week, let me explain.

Recently I was trying to debug an issue where when I would add an instance of an object to the db contenxt sometimes it would take it and sometimes it would not.  I tried for hours to replicate the exact steps so I could narrow down the issue but was not able to.  Here is what I was essentially doing.

dbContext.MyCollection.Add( instance1 );
dbContext.MyCollection.Add( instance2 );
dbContext.MyCollection.Add( instance3 );
(of course my logic was not like this in the actual code, but it did boil down to this)

At the end of my 3 adds I would do dbContext.MyCollection.Count and expect to see 3, but in almost ALL cases I would get  a 1, color me perplexed.  To make it even more perplexing for me is that after each .Add I would check .EntityState of the newly added instance and in EVERY case it was NEW.  I would also hashcode for each instance to ensure they were different and as you may have guessed they were….. WTF

Fast forward a few more hours of my swearing like a drunk sailor, beating my head on my desk I decided to chat with a co-worker of mine whose knowledge in EF is order of magnitude larger than mine.  Although he did not know the direct reason for my pain he did make a magic assertion which lead me to remember something I did a few weeks back.  He said,

Well when you add an instance to the collection EF will essentially just check that object for equality versus all the other objects in the collection to make sure they were different.

The minute he finished that sentence the ‘ah F@CK’ bomb went off in my head.  See a few weeks prior, during very early development of this feature I had this brilliant idea that I needed to override the .Equals() method on my entity objects (yea I know, that was dumb) so I did.  However, as my logic matured over time the .Equals did not keep up because at some point I had realized that I did not need to override that but I was entirely to lazy to delete my overridden method, oh that came back to hurt.

As soon as I realized that this may be the issue I blew away the .Equals() along with my override of GetHashCode() (which actually was simply a pass through to the base implementation) and what do you know, everything simply worked.

The moral of the story here is that when dealing with EF (or any ORM for that matter) I would highly suggest you do not override the .Equals() on your objects, unless you like pain and suffering

till next time,


Posted 04-24-2012 4:46 AM by Derik Whittaker
Filed under:

[Advertisement]

Comments

Joe White wrote re: EF + Overriding Equals == Massive headache
on 04-24-2012 7:17 AM

I dunno... I think the bigger bug was that your Equals and GetHashCode implementations didn't match. (From msdn.microsoft.com/.../system.object.gethashcode.aspx: "If two objects compare as equal, the GetHashCode method for each object must return the same value.") If you had implemented GetHashCode per the guidance, you likely would have noticed the problem the first time you checked the hash codes in the debugger to see if they were different instances.

Of course, you probably left the default GetHashCode precisely so you *could* debug! Tip: If you need to see the default hash code for an object (i.e., based on its reference), you can call the static RuntimeHelpers.GetHashCode method. It returns the default hash code even if you've overridden GetHashCode on your class. You can use it to identify separate instances even if you've followed the guidance for Equals and GetHashCode.

Andrey wrote re: EF + Overriding Equals == Massive headache
on 04-24-2012 10:34 AM

And what about NHibernate, isn't it considered to be a best practice to override Equals and GetHashCode?

Anders Lybecker wrote re: EF + Overriding Equals == Massive headache
on 04-30-2012 6:24 AM

In NHibernate it is recommend to override Equals and GetHashCode. If you don't you will properly end up with problems... with lazy loading, collections, detached entities...

Joe Carr wrote re: EF + Overriding Equals == Massive headache
on 05-14-2012 6:41 PM

It is a best practice to override both Equals & GetHashCode in NHibernate because you as the application developer know best when 2 entities are equal (or not). The same principle I would imagine applies in EF as well. By using the default Equals operator, you can allow 2 instances of the same entity to be added to your collection.

For example, you have 2 person objects which point to the same row in the db. They exist in 2 different locations in memory, but are the same item from the db's perspective.

Perhaps it is desirable to add them both to your "Persons" collection... perhaps not.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)