实体框架核心:永远不会调用属性设置器(是否违反封装?)

Akl*_*kli 6 c# entity-framework-6 entity-framework-core

在EF Core和EF6中,调用属性'Date'的getter(请参见下文)将提供正确的值,但是请注意两者之间的细微差别:在EF Core中,永不调用setter!

这是我的模型:

public class MyModel
{      
    private DateTime _Date;
    private bool dateTimeHasBeenSet = false;
    public DateTime Date
    {
        get
        {
            return _Date;
        }
        set
        {
            dateTimeHasBeenSet = true;
            _Date = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我检索单个项目的方式:

        //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
        }
Run Code Online (Sandbox Code Playgroud)

EF核心是否初始化备份字段而不是属性(通过反射)?这不是违反封装吗?

我正在将一些代码从EF6迁移到EF Core,我真的想避免浪费时间手动调用每个setter背后的逻辑...

编辑:问这个问题让我尝试了一些幻想,如果我将_Property的备份字段重命名为_PropertyX之类的东西(在本例中为_DateX),我的设置器就会被EF Core调用!

Cod*_*und 7

使用EF Core,我们有一个支持字段的概念:

支持字段允许EF读取和/或写入字段而不是属性。

当EF按照惯例发现您的资产有后备字段时,在实现实体时它将使用该字段而不是您的财产。只有在您的实体实现后,并且如果EF需要更新您的实体,它才会在可能的情况下使用该属性(当该属性不是只读的时),否则它将继续使用您的支持字段。

您可以通过执行以下代码来告诉EF Core在实现实体时始终使用您的属性(仅可使用Fluent API):

modelBuilder.Entity<MyModel>()
    .Property(b => b.Date)
    .HasField("_Date")
    .UsePropertyAccessMode(PropertyAccessMode.Property);
Run Code Online (Sandbox Code Playgroud)

要了解有关Backing Fields的更多信息,请点击此处

如果要将此配置应用于模型中的所有属性,则可以使用如下的UsePropertyAccessMode实例方法ModelBuilder

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.Property);
Run Code Online (Sandbox Code Playgroud)

  • @Akli 我更新了如何在整个模型中全局应用它的答案:) (2认同)