簡體   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