Entity framework Core : property setter is never called (Violation of encapsulation?)

c# entity-framework-6 entity-framework-core

Question

The getter for the property "Date" (see below) is used in both EF Core and EF6, but note the little difference between the two: in EF Core, the setter is never called!

This is how I'd act:

public class MyModel
{      
    private DateTime _Date;
    private bool dateTimeHasBeenSet = false;
    public DateTime Date
    {
        get
        {
            return _Date;
        }
        set
        {
            dateTimeHasBeenSet = true;
            _Date = value;
        }
    }
}

This is how I go about getting one thing:

        //Entity Framework 6
        using (Ef6Context context = new Ef6Context())
        {

            var m =  context.MyModels.First();

            // m.dateTimeHasBeenSet is true

        }

        //Entity Framework Core
        using (EfCoreContext context = new EfCoreContext())
        {

            var m = context.MyModels.First();
            // m.dateTimeHasBeenSet is false
        }

Does EF core initialise the backup field using reflection rather than the property? This goes against encapsulation, right?

I really would want to avoid spending time manually running the logic behind each setter since I'm moving some code from EF6 to EF Core.

EDIT : The question prompted me to do a creative experiment: if I change my backup field from _Property to something other like _PropertyX (in this case, _DateX), EF Core suddenly calls my setter!

1
9
11/19/2017 10:44:10 PM

Accepted Answer

We have a concept of backing fields with EF Core:

Backing fields allow EF to read and/or write to a field rather than a property.

When EF detects by convention the existence of a backing field for your property, it will materialise your entity using that field rather than your property. If EF needs to update your entity after it has been materialised, it will utilise the property if at all feasible (provided the property is not read-only); otherwise, it will continue to use your backing field.

By using the following code (only available with Fluent API), you may instruct EF Core to always utilise your property while materialising your entity:

modelBuilder.Entity<MyModel>()
    .Property(b => b.Date)
    .HasField("_Date")
    .UsePropertyAccessMode(PropertyAccessMode.Property);

Go to here for additional information about Backing Fields.

You may use if you wish to apply this setup to every property in your model.UsePropertyAccessMode an illustration ofModelBuilder as follows:

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.Property);
9
11/20/2017 6:45:08 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow