[英]Cycle in models in Entity framework core
Imagine these models are a part of a social network application.想象一下这些模型是社交网络应用程序的一部分。
User
can make a Group
and can add other users in it(as members) and a user can be a member of the group. User
可以创建一个Group
并可以在其中添加其他用户(作为成员),并且用户可以成为该组的成员。 I'm using .net core and also entity framework core.我正在使用 .net 核心和实体框架核心。
Models:楷模:
public class User : BaseEntity
{
public string UserName { get; set; }
public IList<Group> OwnGroups { get; set; }
public IList<GroupMember> MemberInGroups { get; set; }
}
public class Group : BaseEntity
{
public string Name { get; set; }
public int OwnerUserId { get; set; }
[ForeignKey("OwnerUserId")]
public User OwnerUser { get; set; }
public IList<GroupMember> Members { get; set; }
}
public class GroupMember : BaseEntity
{
public int GroupId { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("UserId")]
public Group Group { get; set; }
}
Fluent API:流畅的 API:
modelBuilder.Entity<User>()
.HasMany(x => x.OwnGroups)
.WithOne(x => x.OwnerUser).HasForeignKey(x => x.OwnerUserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<User>()
.HasMany(x => x.MemberInGroups)
.WithOne(x => x.User).HasForeignKey(x => x.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Group>()
.HasMany(x => x.Members)
.WithOne(x => x.Group).HasForeignKey(x => x.GroupId).IsRequired().OnDelete(DeleteBehavior.Cascade);
When I want to migrate to the database, this error happens:当我想迁移到数据库时,会发生这个错误:
Introducing FOREIGN KEY constraint 'FK_GroupMembers_Users_UserId' on table 'GroupMembers' may cause cycles or multiple cascade paths.
在表“GroupMembers”上引入 FOREIGN KEY 约束“FK_GroupMembers_Users_UserId”可能会导致循环或多个级联路径。 Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 Could not create constraint or index.
无法创建约束或索引。 See previous errors.
请参阅以前的错误。
However, I can make this model in SQL Server
manually and there is no problem.但是,我可以在
SQL Server
手动制作这个模型,没有问题。
There are at least two ways to fix it.至少有两种方法可以修复它。 But I want to know why
EF Core
says, there is a cycle.但我想知道为什么
EF Core
说,有一个循环。 What's the problem is?问题是什么?
I think your bridge table has a problem. 我认为您的桥接表有问题。
Try this 尝试这个
public class GroupMember: BaseEntity
{
public User User { get; set; }
[Key, Column(Order = 0)]
public int UserId { get; set; }
public Group Group { get; set; }
[Key, Column(Order = 1)]
public int GroupId { get; set; }
}
First of all: Get rid of the Fluent API part首先:去掉 Fluent API 部分
//modelBuilder.Entity<User>()
//.HasMany(x => x.OwnGroups)
//.WithOne(x => x.OwnerUser).HasForeignKey(x => x.OwnerUserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
//modelBuilder.Entity<User>()
// .HasMany(x => x.MemberInGroups)
// .WithOne(x => x.User).HasForeignKey(x => x.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
//modelBuilder.Entity<Group>()
// .HasMany(x => x.Members)
// .WithOne(x => x.Group).HasForeignKey(x => x.GroupId).IsRequired().OnDelete(DeleteBehavior.Cascade);
And then, based on Microsoft Docs , choose one of these cases:然后,根据Microsoft Docs ,选择以下情况之一:
Change one or more of the relationships to not cascade delete(make it nullable)将一个或多个关系更改为不级联删除(使其可为空)
public int? OwnerUserId { get; set; }
The second approach instead, we can keep the OwnerUserId
relationship required(non-nullable) and configured for cascade delete, but make this configuration only apply to tracked entities, not the database.相反,第二种方法,我们可以保持
OwnerUserId
关系必需(不可为空)并配置为级联删除,但使此配置仅适用于跟踪实体,而不适用于数据库。
modelBuilder .Entity<User>() .HasMany(e => e.OwnGroups) .WithOne(e => e.OwnerUser) .OnDelete(DeleteBehavior.ClientCascade);
In this way, if we want to delete a User
and all its Groups
, we should load both the User
and its Groups
in the application(RAM).这样,如果我们想删除一个
User
及其所有Groups
,我们应该在应用程序(RAM)中加载User
及其Groups
。 Look at this: After running this code, the User
and all its Groups
will be removed.看这个:运行此代码后,
User
及其所有Groups
将被删除。
var context = new MyDbContext();
var user = context.Users.Single(x => x.UserName == "SampleName");
var groups = context.Groups.Where(x => x.OwnerUser == user).ToList();
context.Users.Remove(user);
context.SaveChanges();
But the code below will throw an exception.但是下面的代码会抛出异常。
var context = new MyDbContext();
var user = context.Users.Single(x => x.UserName == "SampleName");
context.Users.Remove(user);
context.SaveChanges();
Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_Groups_Users_OwnerUserId' on table 'Groups' may cause cycles or multiple cascade paths.
Microsoft.Data.SqlClient.SqlException (0x80131904):在表 'Groups' 上引入 FOREIGN KEY 约束 'FK_Groups_Users_OwnerUserId' 可能会导致循环或多个级联路径。 Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.