本文介绍了实体框架 - 流畅的APi - 创建具有2个FK的表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



例如:



产品= StarWar



AssociatedProducts =第V集:帝国反击,第六集:绝地的回归,第七集:力量唤醒



但是EF会生成一些额外列的数据库。



这是我的产品类:

  public class Product 
{
public int Id {get;组; }
public string Name {get;组; }
public string ShortDescription {get;组; }
public string FullDescription {get;组; }
public decimal UnitPrice {get;组; }
......
public virtual ICollection< AssociatedProducts>相关产品{get;组; }
...
}

这是我的AssociatedProduct类:

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

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

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

public virtual产品产品{get;组; }
public virtual Product AssociatedProductsId {get;组;
}

这是我对于AssocietedProduct类的映射:

  public AssociatedProductsMap()
{
//主键
HasKey(a => a.Id);

//属性
属性(a => a.CreatedOn).IsRequired();
属性(a => a.ProductId).IsRequired();
属性(a => a.AssociatedProductId).IsRequired();
属性(a => a.DisplayOrder).IsRequired();

//关系
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 = 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 = correletedProducts},
new Product {Name =StarWar Episode V,ShortDescription =...,FullDescription =P .......,UnitPrice = 15m},
new Product {Name =StarWar剧集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 + ......





但这是我得到的:



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

解决方案

我认为你的课不正确。



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



在这种情况下,EF使用TPH策略。看看这个链接



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



您的映射应该是这样的:

  public class Product 
{
public int ProductId {get;组; }

public string Name {get;组; }

public virtual ICollection< ProductAssociation>相关产品{get;组; }

public virtual ICollection< ProductAssociation>产品介绍组;
}

public class ProductAssociation
{
public int ProductId {get;组; }

public int ProductAssociatedId {get;组; }

public DateTime CreationDate {get;组; }

public virtual Product Product {get;组; }

public virtual Product ProductAssociated {get;组;


public class上下文:DbContext
{
public Context():base(Model2)
{

}

public DbSet< Product>产品{get;组; }
public DbSet< ProductAssociation>产品协会{get;组;

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();


I have this product class which has a list of products associated.

eg:

Product = StarWar

AssociatedProducts = Episode V: The Empire Strikes Back, Episode VI: Return of the Jedi, Episode VII: The Force Awakens

But EF generates the database with some extra columns.

This is my Product Class:

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

This is my AssociatedProduct Class:

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

This is my mapping for AssocietedProduct class:

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

And this is how I am seeding:

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();

This is what I expect from AssociatedProductsId Table:ID + ProductId (FK) + AssociatedProductsId(FK) + date + ......

But this is what I get:

What is my mistake ?Is this a good way to associate a product ?

解决方案

I think your classes are not right.

1 Problem: Why EF generates the table with extra columns?

In that case EF is using TPH strategy. Take a look at this link http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx

2 Problem: What is my mistake ? Is this a good way to associate a product ?

Your mapping should be something like this:

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


}

Seed

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();

这篇关于实体框架 - 流畅的APi - 创建具有2个FK的表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 15:44