【问题标题】:Entity Framework Cascade not deleting children but setting null实体框架级联不删除子级但设置为空
【发布时间】:2021-02-06 17:30:03
【问题描述】:

这是我的两个模型:

public class SystemMessage
{
    [Key]
    public string Id { get; set; }
    public string Name { get; set; }
    public string Message { get; set; }
    public string AdministratorId { get; set; }
    public string Author { get; set; }
    public bool IsActive { get; set; }
    public DateTime CreatedOn { get; set; } = DateTime.Now;
    public DateTime UpdatedOn { get; set; } = DateTime.Now;

    public IList<SystemMessageAttachment> SystemMessageAttachment { get; } = new List<SystemMessageAttachment>();
}

public class SystemMessageAttachment
{
    [Key]
    public string Id { get; set; }
    public string Name { get; set; }
    public string Link { get; set; }
    public string Location { get; set; }
    public string MIMEType { get; set; }
    public string FileType { get; set; }
    public string SystemMessageId { get; set; }
    public virtual SystemMessage SystemMessage { get; set; }
    public DateTime CreatedOn { get; set; } = DateTime.Now;
}

在DbContext中,在onModelCreating函数下,我设置了这个关系:

modelBuilder.Entity<SystemMessageAttachment>()
            .HasOne(b => b.SystemMessage)
            .WithMany(b=>b.SystemMessageAttachment)
            .OnDelete(DeleteBehavior.Cascade);

但是,当我删除系统消息时,它的子附件没有被删除? SystemMessageId 仅设置为 NULL。

我有什么遗漏吗?为什么这里不能级联工作?

编辑: 这就是我删除系统消息的方式:

public bool Delete(string Id)
{
    try
    {
        var a = Get(Id);
        if (a == null)
        {
            return false;
        }
        dbContext.SystemMessage.Remove(a);
        dbContext.SaveChanges();
        return true;
    }
    catch (Exception e)
    {
        logger.LogError(e, "Failed to delete System Message" + " - " + e.Message);
        return false;
    }
}

【问题讨论】:

  • 你是如何删除你的Message的?
  • 您可以验证删除级联是否正确应用于数据库。如果不是,则模型配置有问题。正如有关 DeleteBehavior.Cascade 的文档所述,似乎仅级联删除 in-memory 仅适用于被跟踪实体。这是一种奇怪的设计(或记录在案),因为我们确定有类似on delete cascade 的东西在数据库引擎端实现。 EFCore 确实有办法配置那个东西。作为试用,你能把SystemMessageId 设为required 看看它是如何处理的吗?
  • 顺便说一句,如果您在第一次 db 迁移后刚刚添加了 OnDelete 配置,则需要为该配置更改添加新的迁移并尝试更新目标数据库。如果出现任何错误,您可能需要通过手动脚本修复它。
  • 奇怪,因为我只是快速测试了它,对我来说,当我使用 SystemMessage 实例调用 DbSet.Remove() 时,SystemMessageAttachments 被删除了。所以这些模型和配置似乎不足以重现问题。
  • @ESG 我用删除功能更新了问题。

标签: mysql entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

如果您想使用级联删除,您必须包含子级:

var removingRow=_context.Set<SystemMessage>()
.Include(x=> x.SystemMessageAttachment)
.Where(x => x.Id ==id)
.FirstOrDefault();

if(removingRow != null)
{
_context.Remove(removingRow);
_context.SaveChanges();
}

【讨论】:

  • 感谢您的回答。但是如果我这样手动设置它,它不会破坏要求我的数据库为我处理级联的目的吗?
  • 非常感谢。如果你接受答案就够了。您将其设置为 EF,以便在迁移期间 EF 可以将 DB 设置为允许级联删除。
  • “如果你想使用级联删除,你必须包含子级” - 不,cascade delete 完全由数据库管理,而不是由 EF 管理。因此,无需使用Include 获取孩子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-05
相关资源
最近更新 更多