实体框架代码首先有许多额外的密钥

时间:2015-03-01 19:46:40

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

我正在尝试创建一个链接表,这将允许我在我的产品和附件表之间建立多对多的关系。

我的课程是这样的:

public class Product {
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Accessory> Accessories { get; set; }
}

public class Accessory {
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Machine> Machine { get; set; }
}

public class Type {
    public int Id { get; set; }
    public string Name { get; set; }
}

如果产品属于不同类型,则同一附件可以多次出现在产品上,这将在链接表中确定。像这样:

public class ProductAccessoryLink {
    public int productId {get; set;}
    public int accessoryId {get; set;}
    public int typeId {get; set}
    public int sort {get; set;}
    public string notes {get; set}
}

这是正确的方法。

修改

这是我运行update-database时遇到的错误:

  

引入FOREIGN KEY约束   表上的'FK_dbo.ProductAccessoryLinks_dbo.Types_TypeId'   'ProductAccessoryLinks'可能会导致循环或多个级联路径。   指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他   FOREIGN KEY约束。无法创建约束。见前   错误。

     

这是导致错误的SQL:ALTER TABLE   [dbo]。[ProductAccessoryLinks] ADD CONSTRAINT   [FK_dbo.ProductAccessoryLinks_dbo.Types_TypeId] FOREIGN KEY([TypeId])   REFERENCES [dbo]。[类型]([Id])ON DELETE CASCADE

1 个答案:

答案 0 :(得分:3)

在您的情况下,您需要明确映射联结表。你的模型是这样的:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<ProductAccessoryLink> ProductAccessoryLinks { get; set; }
}

public class Accessory
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<ProductAccessoryLink> ProductAccessoryLinks { get; set; }
}

public class Type
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ProductAccessoryLink 
{
    public int ProductId { get; set; }
    public int AccessoryId { get; set; }
    public int TypeId { get; set; }
    public int sort { get; set; }
    public string notes { get; set; }

    public virtual Type Type { get; set; }
    public virtual Product Product { get; set; }
    public virtual Accessory Accessory { get; set; }
}

您可以通过以下方式配置覆盖上下文中OnModelCreating方法的关系:

protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<ProductAccessoryLink>().HasKey(i => new { i.ProductId, i.AccesoryId, i.TypeId});

    modelBuilder.Entity<ProductAccessoryLink>()
       .HasRequired(i => i.Product)
       .WithMany(k => k.ProductAccessoryLinks)
       .HasForeignKey(i=>i.ProductId);

    modelBuilder.Entity<ProductAccessoryLink>()
       .HasRequired(i => i.Accesory)
       .WithMany(k => k.ProductAccessoryLinks)
       .HasForeignKey(i=>i.AccesoryId);

    modelBuilder.Entity<ProductAccessoryLink>()
       .HasRequired(i => i.Type)
       .WithMany()
       .HasForeignKey(i=>i.TypeId);
}

EF允许您直接配置您尝试的方式的多对多关系。因此,EF负责在数据库中使用它所加入的表的相应键来构建连接表。 (键是连接表的主键和指向连接表的外键)。这使您可以在连接表中获取数据,而无需了解其存在。但是当你想个性化那个表(例如,添加一些其他属性)时,你需要明确地映射它,如上所示。

更新

如果有多个级联删除路径可能会导致尝试删除Types表中的同一行,则会导致该异常。要解决该问题,我建议您在此post

中查看我的答案