首页 文章

实体框架代码首先是多对多的密钥

提问于
浏览
2

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

我的课程是这样的:

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

这是正确的方法吗?

EDIT

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

在表'ProductAccessoryLinks'上引入FOREIGN KEY约束'FK_dbo.ProductAccessoryLinks_dbo.Types_TypeId'可能会导致循环或多个级联路径 . 指定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] . [Types]([Id])ON DELETE CASCADE

1 回答

  • 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检查我的答案

相关问题