在 Entity framework 核心模型中循环
Cycle in models in Entity framework core
假设这些模型是社交网络应用程序的一部分。 User
可以创建一个 Group
并可以在其中添加其他用户(作为成员)并且用户可以是该组的成员。我正在使用 .net 核心和 entity framework 核心。
型号:
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; }
}
流利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);
当我要迁移到数据库时,出现这个错误:
Introducing FOREIGN KEY constraint 'FK_GroupMembers_Users_UserId' on table 'GroupMembers' 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 or index. See previous errors.
不过,我可以在SQL Server
手动中制作这个模型,没有问题。
至少有两种方法可以修复它。但是我想知道为什么EF Core
说,有一个循环。问题是什么?
我认为你的桥 table(路口)有问题。
试试这个
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; }
}
首先:去掉 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);
然后,根据Microsoft Docs,选择以下情况之一:
将一个或多个关系更改为不级联删除(使其可为空)
public int? OwnerUserId { get; set; }
第二种方法,我们可以保留OwnerUserId
relationship required(non-nullable)并配置为级联删除,但是让这个配置只适用于被跟踪的实体,而不是数据库.
modelBuilder
.Entity<User>()
.HasMany(e => e.OwnGroups)
.WithOne(e => e.OwnerUser)
.OnDelete(DeleteBehavior.ClientCascade);
这样,如果我们要删除一个User
和它的所有Groups
,我们应该在应用程序中加载User
和它的Groups
(内存)。看这个:
在 运行 这段代码之后,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();
但是下面的代码会抛出异常。
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. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
假设这些模型是社交网络应用程序的一部分。 User
可以创建一个 Group
并可以在其中添加其他用户(作为成员)并且用户可以是该组的成员。我正在使用 .net 核心和 entity framework 核心。
型号:
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; }
}
流利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);
当我要迁移到数据库时,出现这个错误:
Introducing FOREIGN KEY constraint 'FK_GroupMembers_Users_UserId' on table 'GroupMembers' 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 or index. See previous errors.
不过,我可以在SQL Server
手动中制作这个模型,没有问题。
至少有两种方法可以修复它。但是我想知道为什么EF Core
说,有一个循环。问题是什么?
我认为你的桥 table(路口)有问题。
试试这个
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; }
}
首先:去掉 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);
然后,根据Microsoft Docs,选择以下情况之一:
将一个或多个关系更改为不级联删除(使其可为空)
public int? OwnerUserId { get; set; }
第二种方法,我们可以保留
OwnerUserId
relationship required(non-nullable)并配置为级联删除,但是让这个配置只适用于被跟踪的实体,而不是数据库.modelBuilder .Entity<User>() .HasMany(e => e.OwnGroups) .WithOne(e => e.OwnerUser) .OnDelete(DeleteBehavior.ClientCascade);
这样,如果我们要删除一个User
和它的所有Groups
,我们应该在应用程序中加载User
和它的Groups
(内存)。看这个:
在 运行 这段代码之后,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();
但是下面的代码会抛出异常。
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. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.