【问题标题】:.NET Core Entity Framework many to many relation same entity (related products).NET Core Entity Framework 多对多关系同一实体(相关产品)
【发布时间】:2017-09-08 13:40:14
【问题描述】:

我正在尝试在我的 .NET Core 1.1 MVC 应用程序中使用实体框架构建相关项类型模型。我一直遇到以下错误(尝试了删除行为与外键的所有组合):

引入 FOREIGN KEY 约束 表上的“FK_MenuItemRelation_MenuItems_RelatedMenuItemId” 'MenuItemRelation' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN 关键约束。无法创建约束或索引。见上 错误。

在我开始简单地使用映射表之前,我想听听社区对此的意见。

模型构建器

        //MenuItem <> MenuItem many to many (related item) mapping
        modelBuilder.Entity<MenuItemRelation>()
             .HasKey(mr => new { mr.PrimaryMenuItemId, mr.RelatedMenuItemId });

        modelBuilder.Entity<MenuItemRelation>()
             .HasOne(mr => mr.PrimaryMenuItem)
             .WithMany()
             .HasForeignKey(mr => mr.PrimaryMenuItemId);

         modelBuilder.Entity<MenuItemRelation>()
             .HasOne(mr => mr.RelatedMenuItem)
             .WithMany()
             .HasForeignKey(mr => mr.RelatedMenuItemId).OnDelete(DeleteBehavior.Restrict);

领域模型

public class MenuItem
{
    public string Category { get; set; }
    public string Description { get; set; }
    public long ID { get; set; }
    public Menu Menu { get; set; }
    public string Name { get; set; }
    public string PictureUrls { get; set; }
    public float Price { get; set; }
    public string Reference { get; set; }
    public ICollection<MenuItemRelation> RelatedItems { get; set; }
    public string Status { get; set; }
}

映射实体

public class MenuItemRelation
{
    public MenuItem PrimaryMenuItem { get; set; }
    public long PrimaryMenuItemId { get; set; }
    public MenuItem RelatedMenuItem { get; set; }
    public long RelatedMenuItemId { get; set; }
}

【问题讨论】:

  • 那么,如果你删除一个MenuItemRelation,你也想删除RelatedMenuItem中的MenuItem吗?我是否正确理解了模型构建器的最后一行? (先对EF代码不太熟悉)
  • 如果是这样,什么会阻止这种情况发生:MenuItemA =&gt; RelationAB =&gt; MenuItemB =&gt; RelationBA =&gt; MenuItemA。现在如果RelationABRelationBA 被删除,那么所有内容都会被删除,对吧?
  • 总而言之,这看起来很奇怪。我明白,如果您删除 MenuItem,那么所有使用它作为主键或相关外键的 MenuItemRelations 都应该被删除。这是一条清晰的、非循环的路径。但是,每当删除MenuItemRelation 时删除引用的MenuItem,就会导致各种循环删除盛会。 --(您删除一个关系会导致一个项目被删除,那么另一个(或多个)关系可能会变得无效并且必须被删除,这会导致另一个项目被删除等等)
  • 我觉得我解释得不够好。我想要发生的是,如果那里有相关的菜单项,我将无法删除菜单项。所以我需要先清理所有相关项目,然后才能删除菜单项。我首先有默认设置(即级联)并尝试了任何其他组合,但没有被接受。
  • MenuAMenuB 都与 SubMenuX 相关。你删除了RelationAX,突然MenuB失去了它的关系,因为SubMenuX被删除了......

标签: c# .net asp.net-mvc entity-framework asp.net-core


【解决方案1】:

因此,我对所需的 SQL 结果进行了建模,并使用数据库优先方法对多对多关系进行了逆向工程,如Entity Framework Core creating model from existing database 所述。结果如下。 基本上它只需要我在 menuitem 类上添加传入关系和传出关系。

如果有更好的方法,请随时发表评论。

表 TSQL

Create TABLE MenuItem(
    ID int IDENTITY(1,1),
    Name nvarchar(max)
    PRIMARY KEY (ID)
)

GO

CREATE TABLE MenuItemRelation (
    PrimaryMenuItemId int,
    RelatedMenuItemId int,
    PRIMARY KEY (PrimaryMenuItemId, RelatedMenuItemId),
    FOREIGN KEY (PrimaryMenuItemId) REFERENCES MenuItem (ID),
    FOREIGN KEY (RelatedMenuItemId) REFERENCES MenuItem (ID)
)

GO

Insert into dbo.MenuItem values ('MenuItemA')
Insert into dbo.MenuItem values ('MenuItemB')
Insert into dbo.MenuItem values ('MenuItemC')

GO

INSERT into dbo.MenuItemRelation values (1,2)
INSERT into dbo.MenuItemRelation values (1,3)

GO

DELETE from dbo.MenuItem where ID = 1

GO

//Confirmed no cascading happens

域模型(有一些命名编辑)

public class MenuItem
{
    public string Category { get; set; }
    public string Description { get; set; }
    public long ID { get; set; }
    public Menu Menu { get; set; }
    public string Name { get; set; }
    public string PictureUrls { get; set; }
    public float Price { get; set; }
    public string Reference { get; set; }
    public ICollection<MenuItemRelation> RelatedItems { get; set; }
    public ICollection<MenuItemRelation> RelatedTo { get; set; }
    public string Status { get; set; }
}

映射对象

public class MenuItemRelation
{
    public MenuItem PrimaryMenuItem { get; set; }
    public long PrimaryMenuItemId { get; set; }
    public MenuItem RelatedMenuItem { get; set; }
    public long RelatedMenuItemId { get; set; }
}

模型构建器

modelBuilder.Entity<MenuItemRelation>()
    .HasKey(e => new { e.PrimaryMenuItemId, e.RelatedMenuItemId });

modelBuilder.Entity<MenuItemRelation>()
    .HasOne(d => d.PrimaryMenuItem)
    .WithMany(p => p.RelatedItems)
    .HasForeignKey(d => d.PrimaryMenuItemId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<MenuItemRelation>()
    .HasOne(d => d.RelatedMenuItem)
    .WithMany(p => p.RelatedTo)
    .HasForeignKey(d => d.RelatedMenuItemId)
    .OnDelete(DeleteBehavior.Restrict);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 2022-12-10
    相关资源
    最近更新 更多