[英]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具有幾個特定的屬性,但與佣金沒有關系。
我對“ Parties”表本身的輸出沒有問題,並且了解“ discriminator”字段是什么,但是我不理解它創建的兩個外鍵關系:
我的問題是,為什么我不能僅在后端將各方與Commissions_PartyId建立一個外鍵關系? 如果可以的話,我怎么能告訴EF這樣創建呢?
編輯
使用Dmitry的建議並使用[InverseProperty]屬性,我最終得到了以下數據庫設計,這不是所需的輸出:
它實際上是第三個字段(PartyId1)。 因此,我再次開始查看有關關系的EF 文檔,並開始使用不同的注釋。 使用[ForeignKey(“ PartyId”)]屬性在產生了我期望的設計后,給了我一些希望:
但是,這也產生了一些意外的影響。 在嘗試使用代理商和運營商填充數據庫后,我收到了異常。
這是填充代碼:
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有點瘋狂:)歡迎任何其他想法!
如果您將兩個關系都配置為使用與外鍵相同的屬性,則您仍然有兩個關系。 因此,添加時, Commission
與PartyId
等於1 EF將其解釋為被相關的Agency
與PartyId
等於1 和 Carrier
與PartyId
等於1,顯然這是不可能的。
您需要做的是在Commission
和Party
之間創建一個關系,但這意味着Commissions
導航屬性也需要移到Party
。 但是您仍然可以通過將其設置為受保護對象,並將其僅在Agency
和Carrier
上公開,來將其隱藏在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.