【问题标题】:Entity Framework - Fluent APi - Create table with 2 FK实体框架 - Fluent APi - 使用 2 FK 创建表
【发布时间】:2015-07-16 17:49:10
【问题描述】:

我有一个包含相关产品列表的产品类别。

例如:

产品 = 星球大战

AssociatedProducts = 第五集:帝国反击,第六集:绝地归来,第七集:原力觉醒

但 EF 生成的数据库带有一些额外的列。

这是我的产品类别:

public class Product 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ShortDescription { get; set; }
    public string FullDescription { get; set; }
    public decimal UnitPrice { get; set; }
    ......
    public virtual ICollection<AssociatedProducts> AssociatedProducts { get; set; }
    ......
}

这是我的 AssociatedProduct 类:

public class AssociatedProducts
{
    public int Id { get; set; }

    public int ProductId { get; set; }
    public int AssociatedProductId { get; set; }

    public int DisplayOrder { get; set; }
    public DateTime CreatedOn { get; set; }

    public virtual Product Products { get; set; }
    public virtual Product AssociatedProductsId { get; set; }
}

这是我对 AssociatedProduct 类的映射:

public AssociatedProductsMap()
    {
        // Primary Key
        HasKey(a => a.Id);

        // Properties
        Property(a => a.CreatedOn).IsRequired();
        Property(a => a.ProductId).IsRequired();
        Property(a => a.AssociatedProductId).IsRequired();
        Property(a => a.DisplayOrder).IsRequired();

        //Relationship
        HasRequired(a => a.Products)
            .WithMany(p => p.Products)
            .HasForeignKey(a => a.ProductId)
            .WillCascadeOnDelete(false);

        HasRequired(a => a.AssociatedProductsId)
            .WithMany(p => p.AssociatedProducts)
            .HasForeignKey(a => a.AssociatedProductId)
            .WillCascadeOnDelete(false);

        //Table  
        ToTable("AssociatedProducts");
    }

这就是我播种的方式:

var associetedProducts = new List<AssociatedProducts>
        {
            new AssociatedProducts {ProductId= 1, AssociatedProductId = 3, DisplayOrder = 1, CreatedOn = DateTime.Now},
            new AssociatedProducts {ProductId= 1, AssociatedProductId = 4, DisplayOrder = 2, CreatedOn = DateTime.Now},
            new AssociatedProducts {ProductId= 1, AssociatedProductId = 5, DisplayOrder = 3, CreatedOn = DateTime.Now}
        }

new List<Product>
        {
          new Product {Name = "StarWar", ShortDescription = "...", FullDescription = "P.......", UnitPrice = 15m, AssociatedProducts = associetedProducts},
          new Product {Name = "StarWar Episode V", ShortDescription = "...", FullDescription = "P.......", UnitPrice = 15m},
          new Product {Name = "StarWar Episode VI", ShortDescription = "...", FullDescription = "P.......", UnitPrice = 15m},
          new Product {Name = "StarWar Episode VII", ShortDescription = "...", FullDescription = "P.......", UnitPrice = 15m},
    }.ForEach(a => context.Products.AddOrUpdate(a));

context.SaveChanges();

这是我对 AssociatedProductsId 表的期望: ID + ProductId (FK) + AssociatedProductsId(FK) + 日期 + ......

但这就是我得到的:

我的错误是什么? 这是关联产品的好方法吗?

【问题讨论】:

    标签: c# .net entity-framework ef-code-first ef-fluent-api


    【解决方案1】:

    我认为你的课程不对。

    1 问题:为什么 EF 生成带有额外列的表?

    在这种情况下,EF 正在使用 TPH 策略。看看这个链接http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx

    2 问题:我的错误是什么?这是关联产品的好方法吗?

    你的映射应该是这样的:

    public class Product
    {
        public int ProductId { get; set; }
    
        public string Name { get; set; }
    
        public virtual ICollection<ProductAssociation> AssociatedProducts { get; set; }
    
        public virtual ICollection<ProductAssociation> ProductsAssociatedThisProduct { get; set; }
    }
    
    public class ProductAssociation
    {
        public int ProductId { get; set; }
    
        public int ProductAssociatedId { get; set; }
    
        public DateTime CreationDate { get; set; }
    
        public virtual Product Product { get; set; }
    
        public virtual Product ProductAssociated { get; set; }
    }
    
    public class Context : DbContext
    {
        public Context() : base("Model2")
        {
    
        }
    
        public DbSet<Product> Products { get; set; }
        public DbSet<ProductAssociation> ProductsAssociations { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Product>()
                .HasKey(i => i.ProductId);
    
            modelBuilder.Entity<ProductAssociation>()
                .HasKey(i => new {i.ProductId, i.ProductAssociatedId });
    
            modelBuilder.Entity<Product>()
                .HasMany(i => i.AssociatedProducts)
                .WithRequired(i => i.ProductAssociated)
                .HasForeignKey(i => i.ProductAssociatedId)
                .WillCascadeOnDelete(false);
    
            modelBuilder.Entity<Product>()
                .HasMany(i => i.ProductsAssociatedThisProduct)
                .WithRequired(i => i.Product)
                .HasForeignKey(i => i.ProductId)
                .WillCascadeOnDelete(false);
    
    
            base.OnModelCreating(modelBuilder);
        }
    
    
    }
    

    种子

    var product1 = new Product() { Name = "StarWars", ProductId = 1 };
    
    var product2 = new Product() { Name = "StarWars II", ProductId = 2 };
    
    context.ProductsAssociations.AddOrUpdate(new ProductAssociation { Product = product1, CreationDate = DateTime.Now, ProductAssociated = product2 });
    context.Products.AddOrUpdate(product1);
    context.Products.AddOrUpdate(product2);
    context.SaveChanges();
    

    【讨论】:

    • 嗨@Fabio Luz,非常感谢,我对代码进行了一些更改并且非常接近,唯一的问题是表 ProductAssociation 的 ID 不是自动的尽管此表实际上并不需要自动增量列,但仍会递增。顺便说一句,我可以看出你是巴西人,所以 Obrigado pela ajuda。
    • @Fernando.M 表 ProductAssociation 有一个复合主键。 O ProductId é a FK a qual a associação pertence, o ProductAssociatedId é a FK do produto a qual está sendo associado... a PK da ProductAssociation é 代表 por essas duas colunas, por isso nenhum delas devem ser auto-increment, umas vez que ambas são PK e FK
    • Sim, o auto-increment seria uma coluna chamada Id, ProductId e ProductAssociatedId sao 2 FK a parte, mas como eu disse no comentário acima coluna ID auto-increment não seria necessario.
    • Minha curiosidade é se eu realmente quisesse uma coluna chamada Id como PK, como eu procederia, já que ate então HasKey(a => a.Id); era suficiente para criar a PK.
    • Sim, mas essa coluna nao pode existir porque senão 1 produto poderia ser relacionado com outro produto mais de uma vez... o que não seria correto, certo? por isso as pk é ProductId e ProductAssociatedId。 Mas caso vc realmente quisesse uma coluna nova como pk e auto-increment seria assim: .HasKey(a =&gt; a.Id); .Property(i =&gt; i.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多