Upgrading EntityFramework
Does ApplyCurrentValues() ring a bell for you? If so you’re probably as excited as I am with the latest version of EntityFramework and the simplified APIs for interacting and manipulating object state.
At Wheelhouse almost all of our applications leverage EntityFramework in some way, so I recently embarked on a mission to upgrade us to the latest production release: EF6.1.3. Here are my chronicles.
Upgrade Methodology #
For All Versions #
Steps #
- Upgrade/Install NuGet package EF6.1.3
- Update POCOGenerator.tt
- Update POCOGenerator.Context.tt
- Open the .edmx file and update from database
From EF4.* #
Code Changes #
- context.ContextOptions -> context.Configuration
- .AddObject() -> .Add()
- .RemoveObject() -> .Remove()
- ObjectQuery<> -> IQueryable<>
- SqlCommand/SqlConnection family of methods moved to context.Database This one is debatable, as we don’t actually need to drop a reference to System.Data, and the EF version will behave differently, but something to evaluate on an adhoc basis
- Partial classes can’t have a default constructor
The new POCO generated classes have a constructor that initializes navigation properties. This makes it more difficult to set default values by using a partial class. My solution for this was to create a static constructor ClassName.NewWithDefaults().
Gotchas #
Meta Data Validation #
Meta Data class annotations are now validated on SaveChanges() whereas before they were only utilized by the javascript client-side libraries. This was a breaking change that caused headaches throughout our applications as methods with no changes suddenly started failing at runtime. Luckily we made testing a huge priority and were able to catch all of the significant issues.
Fixup Methods Are Gone #
We had a few places where we were relying on the Fixup behavior. Imagine a class like the following:
class Group {
int id { get; set; }
name string { get; set; }
Batches List<Batch> { get; set; }
}
class Batch {
Group ParentGroup { get; set; }
}
There were cases where we’d create a Group object, and then create an association like this:
var group = new Group();
var batch = new Batch();
batch.Group = group;
context.Groups.Add(group);
context.SaveChanges();
With Fixup behavior, setting the Group property on the batch would also cause the Batch to be added to the collection of Batches on the Group object so that adding the group to the context would also insert all of the batches. Without the fixup behavior, the group would be added, but the batches would not be, and no exceptions would be thrown at that point.