我得到了这样的数据库模型:
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
的sql如下所示:
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 server探查器中看到,当我执行时:
dbContext.Users.Remove(dbContext.Users.Include(x => x.Orders).First(x => x.ID == 1));
EF在删除用户之前会先单独删除所有订单。我认为EF在设置WillCascadeOnDelete(true)
时依赖于SQL server外键中指定的ON DELETE CASCADE
(这是EF中关系的默认行为(。
为什么EF会这样做,我如何告诉EF在删除User
之前不需要删除Order
s?
如果在更改跟踪器中加载了依赖实体,则EF将在SaveChanges((中应用级联行为。
仅应用EF Core模型中配置的删除行为当使用EF Core和从属实体删除主体时实体加载在内存中(即,对于被跟踪的从属项(。A.需要在数据库中设置相应的级联行为确保上下文未跟踪的数据具有必要的已应用操作。如果使用EF Core创建数据库级联行为将为您设置。
https://learn.microsoft.com/en-us/ef/core/saving/cascade-delete#delete-行为
如果你不想那样,那就不要接订单。相反,只是新建一个存根用户并将其删除
var stubUser = new User() {ID = 1};
dbContext.Users.Remove(stubUser);
dbContext.SaveChanges();
您可以使用以下命令删除这些级联删除约定:
//Remove cascade delete conventions
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
■在上面的例子中,EF在构建模型时应用了一组约定(约定适用于所有实体(,您可以用流畅的配置或属性覆盖这些约定,如下所示:
■以下代码配置所需的关系,然后禁用级联删除(仅适用于相关实体(:
modelBuilder.Entity<Course>()
.HasRequired(t => t.Department)
.WithMany(t => t.Courses)
.HasForeignKey(d => d.DepartmentId)
.WillCascadeOnDelete(false);
更新:如果您有受此转换影响的FK
相关数据,则可以使用可为Null的FK,如下所示。上面的代码片段将在数据库中创建一个可以为null的DepartmentId
列,因为我们使用了Nullable<int>
类型(?
是Nullable<int>
的快捷方式(。
public int? DepartmentId { get; set; }