EntityFramework:如何配置级联删除以使外键无效 [英] EntityFramework: How to configure Cascade-Delete to nullify Foreign Keys

查看:167
本文介绍了EntityFramework:如何配置级联删除以使外键无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

EntityFramework的文档指出以下行为是可能的:

EntityFramework's documentation states that the following behavior is possible:


如果从属实体上的外键可为空,则Code First会执行
没有在关系上设置级联删除,当主体是
删除时,外键将设置为null。

If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null.

(来自 http://msdn.microsoft.com/en-us/jj591620

但是,我无法实现这种行为。

However, I cannot achieve such a behavior.

我用代码优先定义了以下实体:

I have the following Entities defined with code-first:

public class TestMaster
{
    public int Id { get; set; }
    public string Name { get; set; }        
    public virtual ICollection<TestChild> Children { get; set; }       
}

public class TestChild
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual TestMaster Master { get; set; }
    public int? MasterId { get; set; }
}

以下是Fluent API映射配置:

Here is the Fluent API mapping configuration:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestMaster>()
                    .HasMany(e => e.Children)
                    .WithOptional(p => p.Master).WillCascadeOnDelete(false);

        modelBuilder.Entity<TestChild>()
                    .HasOptional(e => e.Master)
                    .WithMany(e => e.Children)
                    .HasForeignKey(e => e.MasterId).WillCascadeOnDelete(false);
    }

外键为空,导航属性映射为Optional,所以我希望级联删除按MSDN所述工作,即使所有子级的MasterID无效,然后删除Master对象。

Foreign Key is nullable, navigation property is mapped as Optional, so I expect the cascade delete to work as described as MSDN - i.e. to nullify MasterID's of all children and then delete the Master object.

但是当我实际尝试删除时,我得到了FK违反错误:

But when I actually try to delete, I get the FK violation error:

 using (var dbContext = new TestContext())
        {
            var master = dbContext.Set<TestMaster>().Find(1);
            dbContext.Set<TestMaster>().Remove(master);
            dbContext.SaveChanges();
        }

在SaveChanges()上,它引发以下内容:

On SaveChanges() it throws the following:

System.Data.Entity.Infrastructure.DbUpdateException : An error occurred while updating the entries. See the inner exception for details.
----> System.Data.UpdateException : An error occurred while updating the entries. See the inner exception for details.
----> System.Data.SqlClient.SqlException : The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.TestChilds_dbo.TestMasters_MasterId". The conflict occurred in database "SCM_Test", table "dbo.TestChilds", column 'MasterId'.
The statement has been terminated.

我做错了还是我误解了MSDN的内容?

Am I doing something wrong or did I misunderstood what the MSDN says?

推荐答案

它确实如描述的那样工作,但有关MSDN的文章却没有强调它仅在将子级加载到上下文中时有效同样,不仅是父实体。因此,除了使用 Find (仅加载父级)外,还必须使用 Include (或其他任何项)进行快速加载将子级加载到上下文中的方式):

It works indeed as described but the article on MSDN misses to emphasize that it only works if the children are loaded into the context as well, not only the parent entity. So, instead of using Find (which only loads the parent) you must use eager loading with Include (or any other way to load the children into the context):

using (var dbContext = new TestContext())
{
    var master = dbContext.Set<TestMaster>().Include(m => m.Children)
        .SingleOrDefault(m => m.Id == 1);
    dbContext.Set<TestMaster>().Remove(master);
    dbContext.SaveChanges();
}

这将从数据库中删除主数据库,在 Child 实体为 null 实体,并将子项的UPDATE语句写入数据库。

This will delete the master from the database, set all foreign keys in the Child entities to null and write UPDATE statements for the children to the database.

这篇关于EntityFramework:如何配置级联删除以使外键无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆