Entity framework 首先用额外的键编码多对多

Entity framework code first many to many with extra key

我正在尝试创建一个 linked table,它将允许我在我的产品和配件 table 之间建立多对多关系。

我的类是这样的:

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

如果是不同的类型,同一配件可以多次出现在产品上,这将在 link table 中确定。像这样:

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:

时遇到的错误

Introducing FOREIGN KEY constraint 'FK_dbo.ProductAccessoryLinks_dbo.Types_TypeId' on table 'ProductAccessoryLinks' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

This is the sql causing the error: ALTER TABLE [dbo].[ProductAccessoryLinks] ADD CONSTRAINT [FK_dbo.ProductAccessoryLinks_dbo.Types_TypeId] FOREIGN KEY ([TypeId]) REFERENCES [dbo].[Types] ([Id]) ON DELETE CASCADE

在您的情况下,您需要明确映射路口 table。您的模型将是这样的:

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 负责在数据库中使用它正在加入的 table 的适当键构建一个联接 table。 (这些键都是连接 table 的主键和指向连接的 table 的外键)。这使您可以通过连接 table 获取数据,而无需知道它的存在。但是当你想要个性化 table(例如,添加一些额外的属性)时,你需要像我上面显示的那样显式映射它。

更新

当您有多个级联删除路径时可能会结束尝试删除 Types table 中的同一行时会导致该异常。要解决该问题,我建议您在

中查看我的回答