EF是否可以自动删除孤立的数据,而不删除父数据?

Stu*_*ser 14 c# entity-framework entity-framework-5

对于使用Code First EF 5 beta的应用程序,我有:

public class ParentObject
{
    public int Id {get; set;}
    public virtual List<ChildObject> ChildObjects {get; set;}
    //Other members
}
Run Code Online (Sandbox Code Playgroud)

public class ChildObject
{
    public int Id {get; set;}
    public int ParentObjectId {get; set;}
    //Other members
}
Run Code Online (Sandbox Code Playgroud)

必要时,相关的CRUD操作由存储库执行.

OnModelCreating(DbModelBuilder modelBuilder)
Run Code Online (Sandbox Code Playgroud)

我已经设置了它们:

modelBuilder.Entity<ParentObject>().HasMany(p => p.ChildObjects)
            .WithOptional()
            .HasForeignKey(c => c.ParentObjectId)
            .WillCascadeOnDelete();
Run Code Online (Sandbox Code Playgroud)

因此,如果a ParentObject被删除,它的ChildObjects也是如此.

但是,如果我跑:

parentObject.ChildObjects.Clear();
_parentObjectRepository.SaveChanges(); //this repository uses the context
Run Code Online (Sandbox Code Playgroud)

我得到了例外:

操作失败:无法更改关系,因为一个或多个外键属性不可为空.当对关系进行更改时,相关的外键属性将设置为空值.如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象.

这是有道理的,因为实体的定义包括正在被破坏的外键约束.

我可以将实体配置为在孤立时"清除自己",或者我必须手动ChildObject从上下文中删除这些(在这种情况下使用ChildObjectRepository).

Lad*_*nka 31

它实际上是受支持的,但仅限于使用识别关系时.它首先与代码一起使用.你只需要定义复杂的按键为您ChildObject同时包含IdParentObjectId:

modelBuilder.Entity<ChildObject>()
            .HasKey(c => new {c.Id, c.ParentObjectId});
Run Code Online (Sandbox Code Playgroud)

因为定义此键将删除自动递增的Id的默认约定,您必须手动重新定义它:

modelBuilder.Entity<ChildObject>()
            .Property(c => c.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Run Code Online (Sandbox Code Playgroud)

现在调用parentObject.ChildObjects.Clear()删除依赖对象.

顺便说一句.您的关系映射应该用于WithRequired跟随您的真实类,因为如果FK不可为空,则它不是可选的:

modelBuilder.Entity<ParentObject>().HasMany(p => p.ChildObjects)
            .WithRequired()
            .HasForeignKey(c => c.ParentObjectId)
            .WillCascadeOnDelete();
Run Code Online (Sandbox Code Playgroud)

  • 我看到的许多解决此问题的示例都没有使用对象引用。像在此代码中一样,您可以创建一个外键,因为父属性是一个int'ParentObjectId'。不幸的是,如果您使用完整的OO对象引用,则无法使用,因为您无法使用引用定义外键。这给我带来了同样的问题,孤儿没有被删除。 (2认同)