簡體   English   中英

刪除實體框架創建的連接表的復合主鍵

[英]Remove composite primary key for the join table created by entity framework

我有兩個類,產品和發票,它們之間存在多對多關系

實體框架為我創建了三個表,Products、Invoices 和一個名為 InvoiceProducts(或類似的東西)的連接表

據我所知,默認情況下,實體框架在連接表中的字段InvoiceIdProductId上創建一個復合主鍵,因此這些外鍵一起必須是唯一的。

好吧,這是一個問題,因為有時一個人想在同一個調用中訂購兩個相同的項目。

我看到了這個答案,但它只有在您也在 C# 中創建連接表時才有幫助。 但是當使用實體框架時,我不再創建一個連接表,我只是創建我的類如下:

public class Invoice
{
    public int Id { get; set; }
    public string InvoiceNumber { get; set; }
    public double TotalPrice { get; set; }
    public List<Product> Products { get; set; }
}
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public List<Invoice> Invoices { get; set; }
}
public class DB : DbContext
{
    public DB() : base("MyConnectionstringName") { }

    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<Product> Products { get; set; }
}

那么,有什么想法嗎?

這是多對多表的默認、方便的映射,您只想將兩個表相互關聯。 類似於您所描述的內容可能涉及向 InvoiceProducts 表中添加諸如“數量”之類的內容。 (而不是復制相同的 ProductId+InvoiceId 組合)

這將涉及添加 InvoiceProduct 實體:

public class InvoiceProduct
{
    [Key, ForeignKey(nameof(Invoice), Column(Order=0)]
    public int InvoiceId { get; set; } 
    [Key, ForeignKey(nameof(Product), Column(Order=1)]
    public int ProductId { get; set; } 

    public int Quantity { get; set; }

    public virtual Invoice Invoice { get; set; }
    public virtual Product Product { get; set; }

}

Invoice 和 Product 實體中的導航屬性需要分別更改為 InvoiceProducts 而不是 Products 和 Invoices。 您仍然可以從那里訪問相應的集合,但不太方便,因為集合將被鍵入 InvoiceProduct,這樣您就可以訪問關系的 Quantity 列。 例如,要列出發票的產品,您需要使用invoice.InvoiceProducts.Select(x => x.Product); 而不是invoice.Products

默認的多對多映射更方便,但僅限於表示關系。 映射連接表實體可以讓您更靈活地滿足此類要求。

編輯:另一種方法是使用連接表將多對多替換為一對多對一關系,該連接表具有每個表的 FK 的專用 PK 列。

例如:

public class InvoiceProduct
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int InvoiceProductId { get; set; }
    [ForeignKey(nameof(Invoice), Column(Order=0)]
    public int InvoiceId { get; set; } 
    [ForeignKey(nameof(Product), Column(Order=1)]
    public int ProductId { get; set; } 

    public virtual Invoice Invoice { get; set; }
    public virtual Product Product { get; set; }
}

就個人而言,我更喜歡 Quantity 列中組合 forms 的 PK。 使用這種方法查看數據確實看起來像一個錯誤。 當您查看諸如列出產品的發票之類的東西時,這些通常顯示為產品、價格、數量和總計。 如果我訂購同一產品的 10 個實例,我希望看到該產品的數量為 10,並且同一產品的訂單項總數為 10 個。 使用 Quantity 字段的數據架構或 EF 實現在架構上沒有任何錯誤。 如果您想在刪除產品發票關聯時使用類似軟刪除關聯的方法,則需要相同的方法。 (即一個 IsActive 而不是刪除連接行)這將需要以相同的方式定義一個帶有 IsActive 標志的 InvoiceProduct 實體。 (對於跟蹤諸如 CreatedBy/Date、ModifiedBy/Date 等內容也是如此)

添加數量列在我看來在架構上是錯誤的,對你來說不是嗎?

不,但它是你的數據 model。如果你想要它,那么 model 就像

public class InvoiceLine
{
    public int InvoiceId { get; set; } 
    public int InvoiceLineId { get; set; } 

    public int ProductId{ get; set; } 

    public virtual Invoice Invoice { get; set; }
    public virtual Product Product { get; set; }

}

配置如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Invoice>()
        .HasMany(i => i.Products)
        .WithMany(p => p.Invoices)
        .UsingEntity<InvoiceLine>(
          e => e.HasOne( il => il.Product)
                .WithMany()
                .HasForeignKey(il => il.ProductId),
          e => e.HasOne(il => il.Invoice)
                .WithMany()
                .HasForeignKey(il => il.InvoiceId),
          e => e.HasKey(e => new { e.InvoiceId, e.InvoiceLineId })
        );


    base.OnModelCreating(modelBuilder);
}

請注意您如何仍然擁有多對多並且不必直接處理 InvoiceLine 實體。 它像這樣創建表格

  CREATE TABLE [InvoiceLine] (
      [InvoiceId] int NOT NULL,
      [InvoiceLineId] int NOT NULL,
      [ProductId] int NOT NULL,
      CONSTRAINT [PK_InvoiceLine] PRIMARY KEY ([InvoiceId], [InvoiceLineId]),
      CONSTRAINT [FK_InvoiceLine_Invoice_InvoiceId] FOREIGN KEY ([InvoiceId]) REFERENCES [Invoice] ([Id]) ON DELETE CASCADE,
      CONSTRAINT [FK_InvoiceLine_Product_ProductId] FOREIGN KEY ([ProductId]) REFERENCES [Product] ([Id]) ON DELETE CASCADE
  );


  CREATE INDEX [IX_InvoiceLine_ProductId] ON [InvoiceLine] ([ProductId]);

暫無
暫無

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

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