[英]Entity Framework: WillCascadeOnDelete and Include
我有一个数据库 model 是这样的:
class User
{
public int ID { get; set; }
public string Username { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
class Order
{
public int ID { get; set; }
public string OrderName { get; set; }
public virtual User User { get; set; }
}
我的modelBuilder
配置如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("Users", "dbo");
modelBuilder.Entity<User>().HasKey(x => x.ID);
modelBuilder.Entity<User>().Property(x => x.Username).IsRequired();
modelBuilder.Entity<User>().HasMany(x => x.Orders).WithRequired(x => x.User).WillCascadeOnDelete(true);
modelBuilder.Entity<Order>().ToTable("Orders", "dbo");
modelBuilder.Entity<Order>().HasKey(x => x.ID);
modelBuilder.Entity<Order>().Property(x => x.OrderName).IsRequired();
modelBuilder.Entity<Order>().Property(x => x.UserID).IsRequired();
}
表 dbo.Orders 的dbo.Orders
看起来像:
CREATE TABLE dbo.Orders (
ID int NOT NULL PRIMARY KEY IDENTITY(1, 1),
OrderName nvarchar(256) NOT NULL,
UserID int NOT NULL,
CONSTRAINT FK_Orders_Users FOREIGN KEY (UserID) REFERENCES dbo.Users (ID) ON DELETE CASCADE
);
我可以在 sql 服务器分析器中看到,当我执行时:
dbContext.Users.Remove(dbContext.Users.Include(x => x.Orders).First(x => x.ID == 1));
EF 在删除用户之前单独删除所有订单。 我认为 EF 在设置WillCascadeOnDelete(true)
时依赖于 SQL 服务器外键中指定的ON DELETE CASCADE
(这是 EF 中关系的默认行为)。
为什么 EF 会这样做,我如何告诉 EF 在删除User
之前不需要删除Order
?
您可以使用以下方法删除这些级联删除约定:
//Remove cascade delete conventions
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
■ 在上面的示例中,EF 在构建 model 时应用了一组约定(约定适用于您的所有实体),您可以使用 fluent 配置或属性覆盖约定,如下所示:
■ 以下代码配置所需的关系,然后禁用级联删除(仅适用于相关实体):
modelBuilder.Entity<Course>()
.HasRequired(t => t.Department)
.WithMany(t => t.Courses)
.HasForeignKey(d => d.DepartmentId)
.WillCascadeOnDelete(false);
更新:如果您有受此对流影响的FK
相关数据,则可以使用 Nullable FK,如下所示。 上面的代码片段将在数据库中创建一个可为空的DepartmentId
列,因为我们使用了Nullable<int>
类型( ?
是Nullable<int>
的快捷方式)。
public int? DepartmentId { get; set; }
希望这可以帮助。
如果您在更改跟踪器中加载了相关实体,则 EF 将在 SaveChanges() 中应用级联行为。
EF Core model 中配置的删除行为仅在使用 EF Core 删除主体实体并且在 memory 中加载依赖实体(即,用于跟踪的依赖)时应用。 需要在数据库中设置相应的级联行为,以确保上下文未跟踪的数据应用了必要的操作。 如果您使用 EF Core 创建数据库,则会为您设置此级联行为。
https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete#delete-behaviors
如果你不想这样,那就不要取订单。 相反,只需新建一个存根用户并将其删除。
var stubUser = new User() {ID = 1};
dbContext.Users.Remove(stubUser);
dbContext.SaveChanges();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.