Page 12 - MSDN Magazine, November 2019
P. 12

Data Points JULIE LERMAN
Backing Field and Owned Entity Changes in EF Core 3.0
Well, this is it—the final issue of MSDN Magazine, and the final iter- ation of my column. I’ve decided to write about two of my favorite topics, Entity Framework Core (EF Core) and Domain-Driven Design (DDD). I’ve explored using Entity Framework (EF) and EF Core as a mapper between DDD-influenced domain models and relational databases a number of times over the years. Now EF Core 3.0 has just been released (in September 2019), so I’ll wrap up with a look at some of the improvements that help with these mappings.
My most recent exploration was expressed in a three-part series about EF Core 2.0 as a mapper between DDD models and rela- tional databases. I’ll focus in these last pages on changes brought with EF Core 3.0 that improve the experiences of encapsulating logic with backing fields and of mapping value objects.
Backing Basics in EF Core
EF Core introduced support for backing fields, and each itera- tion brought a better experience with increased support. While backing fields aren’t specific to DDD, they do allow you to encap- sulate properties of your classes, and that’s very important for DDD. The encapsulation lets you more easily control interaction with your classes and APIs to ensure they aren’t intentionally or accidentally misused.
EF6 only maps to properties, not to fields, though it does allow you to protect the value of a property by using a private setter. Because EF uses reflection to materialize query results, it is able to set the value of the property. But the property itself needed to be public:
public string Name {get; private set;}
That covered a lot of cases, but not if you really wanted the prop- erty to be private. A common use case might be the key property. EF needs to interact with it, but you may not want developers to read it directly or even use it in queries.
EF Core’s backing field support can map to backing fields whether you explicitly define backing fields or rely on inferred backing fields to comprehend properties. This allows EF Core to recognize even private properties when creating migrations, as well as to populate them when materializing query results. In this case I'm not even bothering with a getter and setter, but just using an expression body to return _companyId:
private int _companyId;
private int CompanyId =>_companyId;
If the property is private, but you don’t declare a backing field, EF Core will infer it for you when building the data model. In the spe- cific case of making the key private, the ModelBuilder won’t be able to see the private property, so you’ll need to tell EF Core that it’s the key:
modelBuilder.Entity<Company>().HasKey("CompanyId");
EF Core is able to see that there’s a backing field (_companyId) related to the property so it can materialize results to that field, which will then feed the property. If the backing field doesn’t align with the property by convention, you can pair them up with a con- figuration in the DbContext.
Up through 2.2, EF Core would default to reading and writing property values through an available getter and setter even if there was a backing field available, with one exception—when material- izing objects from queries. This exception ensured that any special business logic in a setter would not be triggered just because you were retrieving data from the database.
For example, if you edit the EmployeeCount of the company class, the business rule has a message fired off about the change:
private int _employeeCount; public int EmployeeCount {
get { return _employeeCount; } private set
{
_employeeCount = value;
SendEmployeeCountChangedMessage(); }
That doesn’t make sense if you’re just retrieving the company data from the database. So, because there’s a backing field avail- able, EF Core would set the value using the _employeeCount field.
Backing Field Changes in EF Core 3.0
The team wanted to make sure that as a mapper, EF Core 3.0 aligns better with how we think about object persistence rather than just tying everything to public properties. From Microsoft Program Manager Diego Vega:
“EF Core’s goal should be to facilitate persisting and rehydrating objects from the database, and that is better achieved by mapping the object’s state, which is all represented by the object’s fields (even for automatic properties, there is always a backing field). On the other hand, the decision to add a public property on an object has more to do with the intent to expose specific data from the object to the rest of the program, and should not be determined by persistence concerns.” This truly brings us back to our DDD-focused design.
}
Code download available at msdn.com/magazine/1119magcode.
8 msdn magazine


































































































   10   11   12   13   14