简体   繁体   English

实体框架:WillCascadeOnDelete 和 Include

[英]Entity Framework: WillCascadeOnDelete and Include

I got a database model like this:我有一个数据库 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; }
}

My modelBuilder configurations looks like this:我的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();
}

The sql for table dbo.Orders looks like:表 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
);

I can see in sql server profiler that when im executing:我可以在 sql 服务器分析器中看到,当我执行时:

dbContext.Users.Remove(dbContext.Users.Include(x => x.Orders).First(x => x.ID == 1));

EF is deleting all orders seperatly before it's deleting the user. EF 在删除用户之前单独删除所有订单。 I thought that EF rely on ON DELETE CASCADE specified in SQL server foreign key when setting WillCascadeOnDelete(true) (which is the default behaviour for relationships in EF).我认为 EF 在设置WillCascadeOnDelete(true)时依赖于 SQL 服务器外键中指定的ON DELETE CASCADE (这是 EF 中关系的默认行为)。

Why EF acts like this and how can I tell EF that it's not needed to remove the Order s before removing the User ?为什么 EF 会这样做,我如何告诉 EF 在删除User之前不需要删除Order

You can remove these cascade delete conventions by using:您可以使用以下方法删除这些级联删除约定:

//Remove cascade delete conventions 
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

■ In the above example, EF appllies a set of conventions (convention applies to all your entities) when building the model, and you can override the conventions with the fluent configuration or attributes as shown below: ■ 在上面的示例中,EF 在构建 model 时应用了一组约定(约定适用于您的所有实体),您可以使用 fluent 配置或属性覆盖约定,如下所示:

■ The following code configures the relationship to be required and then disables cascade delete (only for the related entity): ■ 以下代码配置所需的关系,然后禁用级联删除(仅适用于相关实体):

modelBuilder.Entity<Course>()
    .HasRequired(t => t.Department)
    .WithMany(t => t.Courses)
    .HasForeignKey(d => d.DepartmentId)
    .WillCascadeOnDelete(false);

Update: If you have FK related data that to be affected by this convemtion, then you could use Nullable FK as shown below.更新:如果您有受此对流影响的FK相关数据,则可以使用 Nullable FK,如下所示。 The above code snippet will create a nullable DepartmentId column in the database because we have used Nullable<int> type ( ? is a shortcut for Nullable<int> ).上面的代码片段将在数据库中创建一个可为空的DepartmentId列,因为我们使用了Nullable<int>类型( ?Nullable<int>的快捷方式)。

public int? DepartmentId { get; set; }

Hope this helps.希望这可以帮助。

If you have the dependent entities loaded in the change tracker, then EF will apply the cascading behavior in SaveChanges().如果您在更改跟踪器中加载了相关实体,则 EF 将在 SaveChanges() 中应用级联行为。

The delete behavior configured in the EF Core model is only applied when the principal entity is deleted using EF Core and the dependent entities are loaded in memory (that is, for tracked dependents). EF Core model 中配置的删除行为仅在使用 EF Core 删除主体实体并且在 memory 中加载依赖实体(即,用于跟踪的依赖)时应用。 A corresponding cascade behavior needs to be setup in the database to ensure data that is not being tracked by the context has the necessary action applied.需要在数据库中设置相应的级联行为,以确保上下文未跟踪的数据应用了必要的操作。 If you use EF Core to create the database, this cascade behavior will be setup for you.如果您使用 EF Core 创建数据库,则会为您设置此级联行为。

https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete#delete-behaviors https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete#delete-behaviors

If you don't want that, then don't fetch the orders.如果你不想这样,那就不要取订单。 Instead just new-up a stub user and delete it.相反,只需新建一个存根用户并将其删除。

var stubUser = new User() {ID = 1};
dbContext.Users.Remove(stubUser);
dbContext.SaveChanges();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM