簡體   English   中英

EF核心:如何在幾個零/一對多關系之間共享外鍵屬性

[英]EF Core: how to share foreign key properties between several zero/one-to-many relationships

因此,我將略微浸入EF Core,並嘗試繼承和TPH模式(對此我沒有任何經驗)。 EF創建的結果數據庫不是我所期望的,我想知道是否有可能使用fluent-api獲得我正在尋找的結果,或者我是否完全沒注意到這一點。

首先,這是我的POCO課程:

public class Commission
{
    public int Id { get; set; }
    public string Description { get; set; }
    public double Rate { get; set; }
}

public class Party
{
    public int PartyId { get; set; }
    public string Name { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class Agency : Party
{
    public string AgencyCode { get; set; }
    public ICollection<Commission> Commissions { get; set; }
}

public class Carrier : Party
{
    public string CarrierCode { get; set; }
    public ICollection<Commission> Commissions { get; set; }
}

public class Principal : Party
{
    public string Website { get; set; }
    public string DistrictCode { get; set; }
}

還有我的上下文類,以防萬一:

public class PartyContext : DbContext
{
    public DbSet<Agency> Agencies { get; set; }
    public DbSet<Carrier> Carriers { get; set; }
    public DbSet<Party> Parties { get; set; }
    public DbSet<Commission> Commissions { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=LAPTOP-PC\SQLEXPRESS;Database=MyDatabase;Trusted_Connection=True;");
    }
}

基本上,代理,承運人和委托人都繼承自Party,因此它們應具有與Party相同的所有屬性。 代理商和運營商具有其他特定屬性,與佣金之間應為零或一對多的關系。 此外,Principal具有幾個特定的​​屬性,但與佣金沒有關系。

結果數據庫如下: 結果EF數據庫

我對“ Parties”表本身的輸出沒有問題,並且了解“ discriminator”字段是什么,但是我不理解它創建的兩個外鍵關系:

  • 締約方委員會_AgencyPartyId
  • 佣金各方_CarrierPartyId

我的問題是,為什么我不能僅在后端將各方與Commissions_PartyId建立一個外鍵關系? 如果可以的話,我怎么能告訴EF這樣創建呢?

編輯

使用Dmitry的建議並使用[InverseProperty]屬性,我最終得到了以下數據庫設計,這不是所需的輸出: 來自InverseProperty的結果數據庫

它實際上是第三個字段(PartyId1)。 因此,我再次開始查看有關關系的EF 文檔,並開始使用不同的注釋。 使用[ForeignKey(“ PartyId”)]屬性在產生了我期望的設計后,給了我一些希望:

來自ForeignKey屬性的結果數據庫

但是,這也產生了一些意外的影響。 在嘗試使用代理商和運營商填充數據庫后,我收到了異常。

這是填充代碼:

PartyContext _context = new PartyContext();
        // Add an Agency
        var agencyCommission1 = new Commission
        {
            Description = "Contract",
            Rate = 0.075
        };

        var agencyCcommission2 = new Commission
        {
            Description = "Hauling",
            Rate = 0.10
        };

        var agencyCommissionList = new List<Commission>
        {
            agencyCommission1, agencyCcommission2
        };

        var agency = new Agency
        {
            Name = "Agency International",
            Address1 = "12345 Main Street",
            Address2 = "Suite 100",
            City = "Chicago",
            State = "IL",
            Zip = "31202",
            AgencyCode = "AI",
            Commissions = agencyCommissionList
        };

        // Add Carrier
        var carrierCommission1 = new Commission
        {
            Description = "Coal",
            Rate = 0.15
        };

        var carrierCommission2 = new Commission
        {
            Description = "Mining",
            Rate = 0.115
        };

        var carrierCommissionList = new List<Commission>
        {
            carrierCommission1, carrierCommission2
        };

        var carrier = new Carrier
        {
            Name = "Carrier International",
            Address1 = "54321 Main Street",
            Address2 = "Suite 300",
            City = "Cleveland",
            State = "OH",
            Zip = "44115",
            CarrierCode = "CI",
            Commissions = carrierCommissionList
        };

        _context.Agencies.Add(agency);
        _context.Carriers.Add(carrier);

        try
        {
            _context.SaveChanges();
        }
        catch(Exception ex)
        {
            return;
        }

添加代理商時的異常是“無法將類型為'EFTest.Agency'的對象轉換為類型為'EFTest.Carrier'。” 並且嘗試添加載波時的異常是“無法將類型為'EFTest.Carrier'的對象轉換為類型為'EFTest.Agency'。”

我還要補充一點,當使用原始的EF設計時,該程序確實可以按預期運行,但是其他字段和外鍵使我的OCD有點瘋狂:)歡迎任何其他想法!

如果您將兩個關系都配置為使用與外鍵相同的屬性,則您仍然有兩個關系。 因此,添加時, CommissionPartyId等於1 EF將其解釋為被相關的AgencyPartyId等於1 CarrierPartyId等於1,顯然這是不可能的。

您需要做的是在CommissionParty之間創建一個關系,但這意味着Commissions導航屬性也需要移到Party 但是您仍然可以通過將其設置為受保護對象,並將其僅在AgencyCarrier上公開,來將其隱藏在Principal和其他派生類上:

public class PartyContext : DbContext
{
    public PartyContext(DbContextOptions options)
        : base(options)
    {
    }

    public DbSet<Agency> Agencies { get; set; }
    public DbSet<Carrier> Carriers { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Party>().HasMany(typeof(Commission), "Commissions").WithOne();
    }
}

public class Party
{
    public int PartyId { get; set; }
    protected ICollection<Commission> Commissions { get; set; }
}

public class Agency : Party
{
    public new ICollection<Commission> Commissions
    {
        get { return base.Commissions; }
        set { base.Commissions = value; }
    }
}

public class Carrier : Party
{
    public new ICollection<Commission> Commissions
    {
        get { return base.Commissions; }
        set { base.Commissions = value; }
    }
}

public class Commission
{
    public int Id { get; set; }
}

嘗試這個:

public class Commission
{
    public int Id { get; set; }
    public string Description { get; set; }
    public double Rate { get; set; }

    public Party Party { get; set; } // <-- "parent" party link here
}

public class Agency : Party
{
    public string AgencyCode { get; set; }

    [InverseProperty("Party")] // <-- link this collection with Party.Party
    public ICollection<Commission> Commissions { get; set; }
}

public class Carrier : Party
{
    public string CarrierCode { get; set; }

    [InverseProperty("Party")] // <-- link this collection with Party.Party
    public ICollection<Commission> Commissions { get; set; }
}

暫無
暫無

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

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