繁体   English   中英

由于后备字段,EF核心代码首先引发错误的问题

[英]Problem with EF-Core Code first throwing error because of backing field

我无法让我的后备字段正常工作,我尝试使用以下文档尝试了方法: https : //docs.microsoft.com/en-us/ef/core/modeling/backing-field ,没有运气。

当我尝试添加迁移时,遇到此错误:

属性“ Workflow._step1”的类型为“ Step1”,当前数据库提供程序不支持该属性。 更改属性CLR类型或使用'[NotMapped]'属性或'OnModelCreating'中的'EntityTypeBuilder.Ignore'忽略属性。

多个工作流程可以使用同一步骤,所以我希望这样保存它

Workflow 
{
    Id,
    Step1Id
    Step2Id
}

无法使用代码的示例:

public class Workflow 
{
    private Step1 _step1;
    private Step2 _step2;

    public Guid Id { get; set; } = Guid.NewGuid();

    public bool Step1Enabled => true;
    public Step1 Step1 => Step1Enabled ? _step1 : null;

    public bool Step2Enabled => _step1.Completed;
    public Step2 Step2 => _step2Enabled ? _step2 : null;
}

public class Step1 
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public bool StatusUniqueToStep1 { get; set; }
    public bool Completed {get; set; }
}

public class Step2 
{
    public Guid Id { get; private set; } = Guid.NewGuid();
    public bool StatusUniqueToStep2 { get; set; }
    public bool Completed {get; set; }
}

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) :base(options)
    {}

    public DbSet<Workflow> Workflows { get; set; }
    // Tried adding these, does not work.
    // public DbSet<Step1> Step1 { get; set; }
    // public DbSet<Step2> Step2 { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Tried adding these, does not work.
        // modelBuilder.Entity<Step1>();
        // modelBuilder.Entity<Step2>();

        modelBuilder.Entity<Workflow>()
            .Property<Step1>("_step1");

        modelBuilder.Entity<Workflow>()
            .Property<Step2>("_step2");
    }
}

就是这种情况。 根据EF Core的术语,这些不是属性,而是导航属性,因此无法使用Property fluent API进行配置(通常,名称中包含Property / Properties的任何元数据/条目方法都不会返回它们)。

相反,它们是通过与关系相关的流畅API进行配置的。 但是,映射后备字段的问题是没有类似于“属性”的自然流利的API,因此您必须直接使用元数据。

配置可能是这样的:

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step1)
    .WithMany()
    .Metadata.DependentToPrincipal.SetField("_step1");

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step2)
    .WithMany()
    .Metadata.DependentToPrincipal.SetField("_step2");

或考虑到支持字段名称遵循EF Core命名约定之一:

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step1)
    .WithMany()
    .Metadata.DependentToPrincipal.SetPropertyAccessMode(PropertyAccessMode.Field);

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step2)
    .WithMany()
    .Metadata.DependentToPrincipal.SetPropertyAccessMode(PropertyAccessMode.Field);

但这也是EF Core的默认行为。 因此,实际问题不在于支持领域,而是默认情况下EF Core不包括只读 (无设置器)属性(简单或导航都无所谓)的事实。 因此,使这项工作最少的配置是这样的:

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step1);

modelBuilder.Entity<Workflow>()
    .HasOne(e => e.Step2);

更新:为了强制EF Core同时使用set (从数据库中读取)和get (更改跟踪,存储到数据库)的后备字段,请使用第二种配置-带有.Metadata.DependentToPrincipal.SetPropertyAccessMode(PropertyAccessMode.Field)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM