【问题标题】:Cascade Delete doesn't work in Asp.net 5 and EF Core级联删除在 Asp.net 5 和 EF Core 中不起作用
【发布时间】:2021-04-30 16:55:51
【问题描述】:

我正在尝试从数据库中删除UserUser 有自己的Recipes。即使我在模型生成器中配置了级联删除,它也不起作用。

我得到的错误是:

SqlException:DELETE 语句与 REFERENCE 约束“FK_Recipes_AspNetUsers_ApplicationUserId”冲突。冲突发生在数据库“master”、表“dbo.Recipes”、列“ApplicationUserId”中。

AplicationUser.cs

namespace WebApplication.Models
{
    public class ApplicationUser : IdentityUser
    {
        public ICollection<Recipe> Recipes { get; set; }
    }
}

Recipe.cs

namespace WebApplication.Models
{
    public class Recipe
    {
        [Key]
        public Guid Id { get; set; }
        [Required]
        public string RecipeName { get; set; }
        [Required]
        public string RecipeContent { get; set; }
        public string ApplicationUserId { get; set; }
        public ApplicationUser ApplicationUser { get; set; }
    }
}

ApplicationDbContext.cs

namespace WebApplication.Models
{
    public class ApplicationDbContext : IdentityDbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<ApplicationUser>().HasMany(e => e.Recipes).WithOne(e => e.ApplicationUser)
                .OnDelete(DeleteBehavior.ClientCascade);


        }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
        }

        public DbSet<Recipe> Recipes { get; set; }
        public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    }
}

UserController.cs

public IActionResult Delete(string id)
{
    var user = _applicationDbContext.Users
                                    .Where(u => u.Id == id).FirstOrDefault();
    return View(user);
}
      
[HttpPost]
public IActionResult Delete(ApplicationUser appuser)
{
    var user = _applicationDbContext.Users
                                    .Where(u => u.Id == appuser.Id).FirstOrDefault();
    _applicationDbContext.Users.Remove(user);
    _applicationDbContext.SaveChanges();

    return RedirectToAction("Index");
}

我一直在寻找解决方案一个小时,但没有任何效果。

配置 modulbuilder 似乎是几乎每个人的解决方案,但肯定对我不起作用。

【问题讨论】:

  • 您是否一直配置级联删除行为?还是你最近添加的?如果您最近进行了更改,是否记得添加迁移并应用它?

标签: c# asp.net-mvc entity-framework entity-framework-core


【解决方案1】:

ClientCascade 将仅删除由 DbContext 跟踪的相关实体,其中Cascade 还将在数据库中的 FK 约束上设置删除孤儿,如果设置了 EF 来管理架构。

您需要确保 hte DbContext 正在跟踪要删除的相关实体:

var user = _applicationDbContext.Users
    .Include(x => x.Recipies)
    .Where(u => u.Id == appuser.Id)
    .SingleOrDefault();

这可确保 DbContext 了解相关实体,并应在删除用户之前删除这些实体。您还需要了解可能引用用户记录或 FK 的任何其他实体。例如,如果其他记录正在跟踪诸如 CreatedBy 之类的东西,那么这些记录可能会设置为将 FK 返回给用户。依赖ClientCascade 在这里可能会出现问题,级联删除可能不是可取的,而是选择软删除模型。 (即 ApplicationUser 上的 IsActive 标志,而不是删除行)

另外,避免使用First 方法,除非您期望多行并且特别想要第一行。这些方法也只能与OrderBy 方法结合使用。如果您希望有 1 行,请使用 Single。如果您期望 0 或 1 行,请使用 SingleOrDefault。这有助于确保任何意外的数据状态都会导致有意义的异常,而不是默默地做一些意外的事情。

【讨论】:

    【解决方案2】:

    我设法通过更改这一行来解决这个问题: var user = _applicationDbContext.Users.Where(u => u.Id == appuser.Id).FirstOrDefault(); 为此: var user = _userManager.Users.Include(e=>e.Recipes).Where(u => u.Id == appuser.Id).FirstOrDefault();

    【讨论】:

    • 在我完成自己的工作时看到一个答案弹出。 :) 是的,ClientCascase 仅删除跟踪的引用,因此您必须预先加载任何相关实体以确保 DbContext 可以删除它们。
    猜你喜欢
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多