簡體   English   中英

EF Core中具有復合鍵的外鍵

[英]Foreign key with composite key in EF Core

我有以下課程:

    public class ProductAttribute 
    {
        public Guid ProductId { get; set; }

        public Guid AttributeId { get; set; }

        public List<ProductAttributeValue> Values { get; set; }

        public object[] GetKeys()
        {
            return new object[] {ProductId, AttributeId};
        }
    }

    public class Product
    {
        public Guid Id { get; set; }

        public string Name { get; set; }
    }

    public class Attribute
    {
        public Guid Id { get; set; }

        public string Name { get; set; }
    }

    public class ProductAttributeValue
    {
        public Guid Id { get; set; }

        public string Name { get; set; }
    }

在原始情況下,Product和Attribute是AggregateRoot,所以我想通過屬性引用來跳過導航。 值是一個簡單的實體,但我需要在我的ProductAttribute類中作為列表引用,因為您看到該類具有復合鍵。 但我希望在ProductAttribute和ProductAttributeValue之間進行級聯刪除所需的關系。

這個項目是外部模塊,所以我的流暢的API配置是在目標應用程序DbContext OnModelCreating中調用的擴展。 我應該配置每個屬性和引用其他不起作用。

        builder.Entity<ProductAttribute>(b =>
        {
            b.ToTable("ProductAttributes");

            b.HasKey(x => new {x.ProductId, x.AttributeId});

            //I should config ProductAttributeValue one-to-many manually here
        }

        builder.Entity<Product>(b =>
        {
            b.ToTable("Products");

            b.HasKey(x => x.Id);
        }

        builder.Entity<Attribute>(b =>
        {
            b.ToTable("Attributes");

            b.HasKey(x => x.Id);
        }

        builder.Entity<ProductAttributeValue>(b =>
        {
            b.ToTable("ProductAttributeValues");

            b.HasKey(x => x.Id);

            //I should config ProductAttribute many-to-one manually here
        }

如何為ProductAttribute實體配置Fluent API以傳遞此方案?

要根據需要配置所需的關系並級聯刪除,可以在ProductAttribute實體配置塊中使用以下內容:

b.HasMany(e => e.Values)
    .WithOne()
    .IsRequired();

IsRequired就足夠了,因為按照慣例,級聯刪除是必需的,關閉是可選的關系。 當然,如果你願意,你可以添加.OnDelete(DeleteBehavior.Cascade) - 這將是多余的,但不會受到傷害。

請注意,應該在一個地方配置關系。 所以在ProductAttributeProductAttributeValue執行它,但從ProductAttributeValue兩者中(容易出錯,可能導致意外的沖突或覆蓋配置問題)。

為了完整HasOne ,以下是如何在ProductAttributeValue配置中配置相同的內容(由於缺少導航屬性,需要顯式提供HasOne泛型類型參數):

b.HasOne<ProductAttribute>()
    .WithMany(e => e.Values)
    .IsRequired();

編寫ProductAttribute配置如下:

modelBuilder.Entity<ProductAttribute>(b =>
{
    b.ToTable("ProductAttributes");

    b.HasKey(x => new {x.ProductId, x.AttributeId});

    b.HasMany(pa => pa.Values).WithOne().IsRequired();
});

但是人們擔心可讀性。 這會將ProductAttributeProductIdProductAttributeAttributeId列作為復合外鍵添加到shadow屬性的表ProductAttributeValues中。 如果要使表ProductAttributeValues復合外鍵更具可讀性,則可以按如下方式更新模型ProductAttributeValue模型類:

public class ProductAttributeValue
{
    public Guid Id { get; set; }

    public Guid ProductId { get; set; }

    public Guid AttributeId { get; set; }

    public string Name { get; set; }
}

然后按如下方式更新ProductAttribute配置:

modelBuilder.Entity<ProductAttribute>(b =>
{
    b.ToTable("ProductAttributes");

    b.HasKey(x => new {x.ProductId, x.AttributeId});

    b.HasMany(pa => pa.Values).WithOne().HasForeignKey(pa => new {pa.ProductId, pa.AttributeId});
});

現在,表ProductAttributeValues復合外鍵將生成為ProductIdAttributeId

謝謝。

暫無
暫無

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

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