实体框架 - Fluent APi - 使用2 FK创建表格

时间:2015-07-16 17:49:10

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

我有这个产品类,其中包含相关产品列表。

例如:

产品= StarWar

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; }
}

这是我对AssocietedProduct类的映射:

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)+ date + ......

enter image description here

但这就是我得到的: enter image description here

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

1 个答案:

答案 0 :(得分: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();