【问题标题】:Composite key entity and dont want to declare PK keys复合键实体且不想声明 PK 键
【发布时间】:2023-03-26 08:54:01
【问题描述】:

好的,这应该很简单。我有课

public class ProductConfig
{
   public Category { get;set; }
   public Product { get;set; }
}

这两个导航属性也是表格的主键。 声明 PRoductId 和 CategoryId 是多余的。如何使用导航属性配置主键?

编辑:愚蠢的我。我在上面的问题中忘记了一些非常重要的事情。上面那两个是为了指出配置。然后我们有第三个 fk,它是 Product 和 category 组合的选定配置。所以上面的实体一定是物化实体

public class ProductConfig
{
   public Category { get;set; }
   public Product { get;set; }
   public ProductCategoryType { get; set; }
}

【问题讨论】:

    标签: c# entity-framework entity-framework-6 ef-code-first


    【解决方案1】:

    声明 ProductId 和 CategoryId 是多余的。如何使用导航属性配置主键?

    很快 - 你不能。虽然 EF6 支持基于影子属性的 FK,但它不提供使用影子属性名称配置 PK(和许多其他列相关设置)的方法 - [Key][Column]data 注释不能应用于导航属性和 @987654323 @fluent API 需要原始属性选择器表达式。一般 EF6 不支持 PK 中的阴影属性。

    所有这些限制都已在 EF Core 中删除。但在 EF6 中,无论是否冗余,您必须在实体中定义实际的原始属性并将它们映射到复合 PK。

    【讨论】:

    • 好吧,很伤心。我添加了 PK 和标准 HasRequired(...).WithMany().HasForeignKey(...);哪个有效
    【解决方案2】:

    您只需通过导航属性设置产品和类别实体之间的关系。 EF会根据自己的多对多关系建立正确的表结构。所以不需要自己的关系实体。 请查看:many-to-many-relationship in EF

    例如:

    产品类别:

    public class Product
    {
        // other properties
    
        public virtual ICollection<Category> Categories { get; set; }
    }
    

    类别类:

    public class Category
    {
        // other properties
    
        public virtual ICollection<Product> Products { get; set; }
    }
    

    还是我误解了你的问题?

    编辑: 如果您需要像 ProductConfig 这样的单独实体,则应尝试通过以下方式将其设置为唯一索引约束:

    modelBuilder
        .Entity<ProductConfig>()
        .HasIndex(pc => new {pc.Category, pc.Product})
            .IsUnique();
    

    如需更多信息,请阅读:HasIndex - Fluent API

    EDIT 2获取信息后解决方案是 EF ):

    在您最后一次问题编辑之后,需要另一种解决方法。 来了……

    您需要如下结构:

    产品

    public class Product
    {
        // other properties
    
        public virtual ICollection<ProductConfig> ProductConfigs { get; set; }
    }
    

    类别

    public class Category
    {
        // other properties
    
        public virtual ICollection<ProductConfig> ProductConfigs { get; set; }
    }
    

    产品配置

    public class ProductConfig
    {
        // other properties
    
       public virtual Category { get; set; }
    
       public virtual Product { get; set; }
    
       public virtual ProductCategoryType { get; set; }
    }
    

    要在 EF

    modelBuilder.Entity<ProductConfig>()
            .Property(e => e.Category)
            .HasColumnAnnotation(
                IndexAnnotation.AnnotationName, 
                new IndexAnnotation(new IndexAttribute("YourIndex", 1) { IsUnique = true }));
    
    modelBuilder.Entity<ProductConfig>()
            .Property(e => e.Product)
            .HasColumnAnnotation(
                IndexAnnotation.AnnotationName, 
                new IndexAnnotation(new IndexAttribute("YourIndex", 2) { IsUnique = true }));
    
    modelBuilder.Entity<ProductConfig>()
            .Property(e => e.ProductCategoryType)
            .HasColumnAnnotation(
                IndexAnnotation.AnnotationName, 
                new IndexAnnotation(new IndexAttribute("YourIndex", 3) { IsUnique = true }));
    

    在 EF 6.2 中:

    modelBuilder.Entity<Person>()
        .HasIndex(p => new { p.Category, p.Product, p.ProductCategoryType })
        .IsUnique();
    

    编辑 3 如果您的 ProductConfig 类中没有主键,或者您在我没有添加的示例中使用了我的主键,因为我认为您已经拥有该类。 可以将多个属性设置为键。这也会产生独特的组合。 您将使用以下内容存档 - 而不是索引内容:

    modelBuilder.Entity<ProductConfig>()
                .HasKey(pc => new { pc.Category, pc.Product, pc.ProductCategoryType });
    

    如需更多信息,请查看MS docs

    您也可以添加一个 Id 作为主键,而不是需要索引。

    【讨论】:

    • 我们希望将复合表作为一个实体进行查询。但是现在当我想到它时,也许我们不需要那个。因为我们总是使用一个类别或一个产品作为起点。让我试试..
    • ops,我在我的问题中忘记了一个非常重要的事情。我现在编辑
    • 好吧,我已经添加了更多信息来归档具有附加属性或更多属性的复合表的目标。
    • 嗯,我们使用 EntityTypeConfiguration 类,它没有 HasIndex 方法。我想知道我是否需要升级EF。还是在使用 EntityTypeConfiguration 时命名不同?
    • 似乎是 6.2 的功能,我们在 6.1.3。升级
    猜你喜欢
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多