14

I have read few articles (article1, article2) about Entity Framework that it calls DetectChanges many times, which makes it very slow when working with large amounts of data.

Can i, for example, disable the autoDetectChanges when i initialize the context, and just call DetectChanges() before calling .SaveChanges()?

Will the context recognize the inserted/changed/deleted entities?

var _dbContext = new ProjectContext();
_dbContext.Configuration.AutoDetectChangesEnabled = false;

// add/edit/delete entities

_dbContext.ChangeTracker.DetectChanges();
_dbContext.SaveChanges();

Should this approach work? or it may create hidden bugs?

Community
  • 1
  • 1
Catalin
  • 11,503
  • 19
  • 74
  • 147
  • not 100% sure if it does anything weird in the background, but I have been using a similar approach without finding any bad side effects – Thewads Mar 11 '13 at 16:05

2 Answers2

21

Arthur Vickers defines a rule when DetectChanges doesn't need to be called (even not before SaveChanges) in this blog post:

No call to EF code will leave the context in a state where DetectChanges needs to be called if it didn’t need to be called before.

Regarding Add and Delete these are "EF code" methods because you either call Add or Delete or you set the state of context.Entry(entity).State to Added or Deleted. So, if you would just loop through a bunch of entites and add or delete them then you don't need to call DetectChanges at all.

Regarding Edit it is, I believe, a bit more subtle. When you update entities by using either...

context.Entry(entity).CurrentValues.SetValues(someObject);

...or by using the property API of DbContext...

context.Entry(entity).Property(e => e.SomeProperty).CurrentValue = someValue;

...then you don't need DetectChanges (even not before SaveChanges) either because these are again calls into "EF code".

If you just change property values of an entity like...

entity.SomeProperty = someValue;

...then the second rule in the same blog post linked above applies:

Any time that non-EF code changes any property value of an entity or complex object then DetectChanges may need to be called.

And I think you need in fact only one single call to DetectChanges before SaveChanges if you just loop through some entities, load them into or attach them to the context and change some (scalar and complex) property values.

If you do more complex stuff (maybe relationship changes? or something else?) your approach might not be safe anymore because

  1. AutoDetectChanges would not be implemented in the way it is and called in many EF methods if it would be only necessary once right before SaveChanges

  2. it is mentioned in the same blog post again that

    If the code makes change changes to the properties of the entities instead of just calling Add or Attach, then, by Rule 2, DetectChanges will need to be called, at least as part of SaveChanges and possibly also before then.

    (Highlighting from me)

Unfortunately I don't know an example of code that would show when calling DetectChanges at earlier stages than right before SaveChanges is necessary. But because of point 1 above I am sure such examples exist.

Community
  • 1
  • 1
Slauma
  • 175,098
  • 59
  • 401
  • 420
  • 1
    That was a great post, thank you. But i am a little unclear (sorry for this): 1. Why EF needs to call DetectChanges so many times when it could just call DetectChanges before actually saving into database? 2. I am using `POCO` objects with normal properties (not marked with `virtual`). When i change the object properties values, does EF calls DetectChanges() silently? – Catalin Mar 12 '13 at 07:31
  • @RaraituL: To point 1: I don't know. That's what I meant with my very last sentence. To point 2: No. `DetectChanges` is called later in `SaveChanges` and a bunch of other EF methods, not when you assign property values. `DetectChanges` compares then the current property values with the original values (that are stored as a "snapshot" in object context) and if the values changed the properties will be marked as modified. It's called "snapshot based change tracking". – Slauma Mar 12 '13 at 12:08
-1

One of the main problems that can be resolved by DetectChanges is persisting data in EF when we have ManyToMany relation and AutoDetectChanges=false.

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
MMB
  • 11
  • 1