C# 实体框架 (EF) 代码优先级联删除,用于一对零或一关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17487577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:36:51  来源:igfitidea点击:

Entity Framework (EF) Code First Cascade Delete for One-to-Zero-or-One relationship

c#entity-frameworkef-code-firstentity-framework-5cascading-deletes

提问by arsenalogy

Following the "Code First Modeling" section of the Pluralsight "Getting Started with Entity Framework 5" course by Julie Lerman, I created two POCO classes with a one-to-zero-or-onerelationship: a parent (User) and an optionalchild (UserDetail).

按照Julie LermanPluralsight“实体框架 5 入门”课程的“代码优先建模”部分,我创建了两个具有一对零或一关系的POCO 类:一个父类(用户)和一个可选的子(用户详细信息)。

User and UserDetail data model diagram (click to view).

User 和 UserDetail 数据模型图(点击查看)。

Notice in the diagram that the UserId property is a primary key and a foreign key for UserDetail.

请注意图中的 UserId 属性是 UserDetail 的主键和外键

Relevant code:

相关代码:

public class User
{
    //...

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    /* Has a 1:0..1 relationship with UserDetail */
    public virtual UserDetail UserDetail { get; set; }

    //...
}

public class UserDetail
{
    //...

    /* Has a 0..1:1 relationship with User */
    public virtual User User { get; set; }

    [Key, ForeignKey("User")]
    public int UserId { get; set; }

    //...
}

public class EFDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    //public DbSet<UserDetail> UserDetails { get; set; }  /* Explicit declaration not necessary. Context is aware of UserDetail entity due to 0..1:1 relationship with User */

    public EFDbContext()
    {
        Configuration.ProxyCreationEnabled = true;
        Configuration.LazyLoadingEnabled = true;
    }
}

public class UserRepository : IUserRepository
{
    private EFDbContext _context = new EFDbContext();

    public void Delete(User entity)
    {
        entity = _context.Users.Find(entity.UserId);

        //...

        _context.Users.Remove(entity);
        _context.SaveChanges();

        //...
    }
}

When the Delete() method in the UserRepository class is called, it does not delete the User record in the database because the foreign key in UserDetail does not have cascade delete enabled.

调用 UserRepository 类中的 Delete() 方法时,不会删除数据库中的 User 记录,因为 UserDetail 中的外键没有启用级联删除。

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.UserDetail_dbo.User_UserId".

DELETE 语句与 REFERENCE 约束“FK_dbo.UserDetail_dbo.User_UserId”冲突。

How would you enable cascading deletes for one-to-zero-or-one relationshipsusing Entity Framework Code First (so that deleting a User automatically deletes UserDetail)?

您将如何使用 Entity Framework Code First为一对零或一关系启用级联删除(以便删除用户会自动删除 UserDetail)?

采纳答案by hutchonoid

You will have to use the fluent API to do this.

您将不得不使用 fluent API 来执行此操作。

Try adding the following to your DbContext:

尝试将以下内容添加到您的DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{   
    modelBuilder.Entity<User>()
        .HasOptional(a => a.UserDetail)
        .WithOptionalDependent()
        .WillCascadeOnDelete(true);
}

回答by Lupa

This code worked for me

这段代码对我有用

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserDetail>()
            .HasRequired(d => d.User)
            .WithOptional(u => u.UserDetail)
            .WillCascadeOnDelete(true);
    }

The migration code was:

迁移代码是:

public override void Up()
    {
        AddForeignKey("UserDetail", "UserId", "User", "UserId", cascadeDelete: true);
    }

And it worked fine. When I first used

它工作得很好。当我第一次使用

modelBuilder.Entity<User>()
    .HasOptional(a => a.UserDetail)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);

The migration code was:

迁移代码是:

AddForeignKey("User", "UserDetail_UserId", "UserDetail", "UserId", cascadeDelete: true); 

but it does not match any of the two overloads available (in EntityFramework 6)

但它与可用的两个重载中的任何一个都不匹配(在 EntityFramework 6 中)

回答by rajeemcariazo

You could also disable the cascade delete convention in global scope of your application by doing this:

您还可以通过执行以下操作在应用程序的全局范围内禁用级联删除约定:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()