一個客戶有多個地址,一個倉庫有一個地址。我的 C# 代碼如下所示:
public class Address
{
public int Id { get; set; }
public string Text { get; set; }
public Client Client { get; set; }
public Warehouse Warehouse { get; set; }
}
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
public int? AddressId { get; set; }
public IList<Address> Addresses { get; set; }
}
public class Warehouse
{
public int Id { get; set; }
public string Name { get; set; }
public int? AddressId { get; set; }
public Address Address { get; set; }
}
以下是表格的外觀。我將添加一些示例資料來說明我的觀點:
地址
───── ──────────────────── ───────────
| Id | Text | ClientId |
───── ──────────────────── ───────────
| 1 | Address of WH 1 | |
| 2 | Address of WH 2 | |
| 3 | Address 1 of Cl 2 | 1 |
| 4 | Address 2 of Cl 1 | 2 |
| 5 | Address 1 of Cl 1 | 2 |
───── ──────────────────── ───────────
客戶
───── ─────────── ────────────
| Id | Name | AddressId |
───── ─────────── ────────────
| 1 | Client 2 | (null) |
| 2 | Client 1 | (null) |
| 3 | Client 3 | (null) |
───── ─────────── ────────────
倉庫
───── ────────────── ────────────
| Id | Name | AddressId |
───── ────────────── ────────────
| 1 | Warehouse 1 | 1 |
| 2 | Warehouse 2 | 2 |
───── ────────────── ────────────
我的目標是在地址中沒有ClientId列。相反,對于每個AddressId,在 Clients 中添加一個額外的條目。地址也會隨著客戶端的洗掉而被級聯洗掉。
───── ─────────── ────────────
| Id | Name | AddressId |
───── ─────────── ────────────
| 1 | Client 2 | 4 |
| 1 | Client 2 | 5 |
| 2 | Client 1 | 1 |
| 3 | Client 3 | (null) |
───── ─────────── ────────────
uj5u.com熱心網友回復:
您的原始架構有些損壞,您提出的更改更糟。每個表都應該有一個唯一的 PK。如果您開始將表中的 ID 加倍,則意味著您正在使用客戶端 ID 和地址 ID 之間的復合 PK,除非這不適用于沒有地址的客戶端。(#null 地址 ID)
您正在尋找的是地址和客戶之間的多對多關系:
從表的角度來看:
地址
───── ────────────────────
| Id | Text |
───── ────────────────────
| 1 | Address of WH 1 |
| 2 | Address of WH 2 |
| 3 | Address 1 of Cl 2 |
| 4 | Address 2 of Cl 1 |
| 5 | Address 1 of Cl 1 |
───── ────────────────────
客戶
───── ───────────
| Id | Name |
───── ───────────
| 1 | Client 2 |
| 2 | Client 1 |
| 3 | Client 3 |
───── ───────────
客戶地址
────────── ───────────
| ClientId | AddressId |
────────── ───────────
| 1 | 4 |
| 1 | 5 |
| 1 | 1 |
────────── ───────────
從物體的角度來看,Client 可以有一個 Addresses 的集合,Addresses 可以選擇有一個 Clients 的集合。
public class Address
{
public int Id { get; set; }
public string Text { get; set; }
}
public class Client
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; } = new List<Address>();
}
地址不會參考倉庫,而是倉庫會通過 AddressId 參考地址。
public class Warehouse
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Address Address { get; set; }
}
連接客戶端和地址意味著建立多對多關系。這可以在 DbContext 的 OnModelCreating 事件處理程式中完成:
// 英法 6
modelBuilder.Entity<Client>()
.HasMany(x => x.Addresses)
.WithMany()
.Map(x => { x.MapLeftKey("ClientId"); x.MapRightKey("AddressId"); x.ToTable("ClientAddresses"); });
modelBuilder.Entity<Warehouse>()
.HasOptional(x => x.Address)
.WithMany()
.Map(x => x.MapKey("AddressId"));
在 EF Core 中,映射看起來有點不同,并且取決于您可能使用的版本,可能需要也可能不需要將 ClientAddresses 定義為物體類。(需要 EF Core 3.1 及更早版本,不需要 EF Core 5/6)
而 Warehouse 表將有一個地址 ID 指向它的地址,并且可能有一個客戶端 ID 指向客戶端。(取決于這兩者之間的關系)當使用導航屬性時,我強烈建議不要將 FK 宣告為物體中的屬性。這會創建兩個可能不匹配的事實來源,并在更新時導致不一致的行為,具體取決于導航屬性是否已加載。相反,我建議對 FK 欄位使用陰影屬性并始終使用導航屬性。(速度對于批量更新更重要,使用 FK 并省略導航屬性) EF Core 中更好地支持陰影屬性,因此它們的映射與我上面的不同。(EF6)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/459586.html
上一篇:復習 - es6語法
下一篇:物體框架更新條目重復鍵
