簡體   English   中英

EF Core 3.1 - DDD 和 inheritance

[英]EF Core 3.1 - DDD and inheritance

我正在開發一個主要管理員工和承包商的遺留應用程序。 下面是 EF Core 3.1 舊版 model 的摘錄。 完整的源代碼可在此處獲得。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ManagerId { get; set; }
    public virtual Person Manager { get; set; }
}

public class Employee : Person
{
    public int Grade { get; set; }
}

public class Contractor : Person
{
    public int ContractorId { get; set; }
    public virtual ContractingCompany Company { get; set; }
}

public class ContractingCompany
{
    public int Id { get; private set; }
    public string Name { get; private set; }
    private readonly List<Contractor> _contractors = new List<Contractor>();
    public virtual IReadOnlyList<Contractor> Contractors => _contractors;

    protected ContractingCompany()
    {
    }

    public ContractingCompany(string name) : this()
    {
        Name = name;
    }

    public void Add(Contractor contractor)
    {
        _contractors.Add(contractor);
    }
}

在此處輸入圖像描述

這些實體從我們使用 TPH 策略的同一個表中提取數據。

我們正在擴展我們的應用程序並將承包商重命名為合作伙伴。 這次我們決定使用 DDD go 並讓新模型使用表拆分讀取現有數據。 當我們將內容移至新的 model 時,我們需要保持應用程序正常工作,因此在所有用例都移至新的 DDD Z20F35E630DAF44DBFA4C3F68F5399D8 之前,我們無法完全刪除舊版 model。

DDD model 如下,將從現有數據庫中拉取數據:

public class Partner /* Pulls data from the Contracting Company */
{
    public int Id { get; set; }
    public string Name { get; set; }
    private readonly List<PartnerEmployee> _employees = new List<PartnerEmployee>();
    public virtual IReadOnlyList<PartnerEmployee> Employees => _employees;
    protected Partner(){}
}

public class PartnerEmployee /* Pulls data from the Contractor table */
{
    public int Id { get; set; }
    public int ContractorId { get; set; }
}

EF 映射如下:

public class PartnerConfiguration : IEntityTypeConfiguration<Partner>
{
    public void Configure(EntityTypeBuilder<Partner> builder)
    {
        builder.ToTable("ContractingCompany");
        builder.HasKey(c => c.Id);
        builder.Property(c => c.Id).HasColumnName("Id");
        builder.Property(c => c.Name).HasColumnName("Name");
        builder.HasOne<ContractingCompany>().WithOne().HasForeignKey<Partner>(c => c.Id);
    }
}

public class PartnerEmployeeConfiguration : IEntityTypeConfiguration<PartnerEmployee>
{
    public void Configure(EntityTypeBuilder<PartnerEmployee> builder)
    {
        builder.ToTable("Person");
        builder.HasKey(c => c.Id);
        builder.Property(c => c.Id).HasColumnName("Id");
        builder.Property(c => c.ContractorId).HasColumnName("ContractorId");
        builder.Property<int?>("PartnerId").HasColumnName("CompanyId");
        builder.HasOne<Contractor>().WithOne().HasForeignKey<PartnerEmployee>(c => c.Id);
    }
}

問題:我們正在嘗試從數據庫中讀取現有數據:

var contractingCompany = context.ContractingCompanies.First(); <-- Works fine
var partner = context.Partners.First(); <-- Crashes

上面的第二行拋出異常:

Microsoft.Data.SqlClient.SqlException:
列名“Contractor_CompanyId”無效。
列名“ContractorId1”無效。

誰能幫我理解為什么 EF 查找列Contractor_CompanyId ContractorId1

看起來為參與表拆分(PK 除外)的實體的屬性配置列名會使其他參與實體/實體的常規列名無效。

不幸的是,表格拆分文檔中沒有解釋這種行為(它應該),只有一個小文本到隨附的示例中說

除了所需的配置,我們將Property(o => o.Status).HasColumnName("Status")調用到DetailedOrder.Status到與Order.Status相同的列。

然后您可以在示例流式配置中看到Property(o => o.Status).HasColumnName("Status")OrderDetailedOrder調用。

很快,您必須兩個(如果多於一個)實體顯式配置共享列的列名。

在您的情況下,所需的最小配置(除了您當前擁有的)是這樣的(直接使用modelBuilder fluent API,但如果您願意,可以將它們放在單獨的實體配置類中):

modelBuilder.Entity<ContractingCompany>(builder =>
{
    builder.Property(c => c.Name).HasColumnName("Name");
});

modelBuilder.Entity<Contractor>(builder =>
{
    builder.Property(c => c.ContractorId).HasColumnName("ContractorId");
    builder.Property("CompanyId").HasColumnName("CompanyId");
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM