6

实体A,B的关系是一对多的,(A有很多B,B必须属于A)。

我像这样禁用lazy loading并加载A,B:

dbContext.As.Load();
//**particaly load B** 
dbContext.Bs.Where(predicateX).Load();

当我使用

dbContext.As.Remove(someA)

要删除A,我遇到以下错误消息

The relationship could not be changed because one or more of the foreign-key properties is non-nullable

相反,如果我使用:

//remove all B in someA
foreach(B b in someA.Bs.ToList())
{
   dbContext.Bs.Remove(b);
}
dbContext.As.Remove(someA)

一切都好。

有一个更好的方法吗?

编辑


我正在使用 Database First 并在数据库端添加 B 的外键约束(在删除级联上)。

我认为“外键约束”就等于代码“OnModelCreating”。但代码“dbContext.As.Remove(someA)”没有按预期工作。

当存在 ABC 级联一对多关系时,情况会变得更糟。为了删除一些 A,你需要这样做

foreach(B b in someA.Bs.ToList())
{
  foreach(C c in b.Cs.ToList())
  {
    dbContext.Cs.Remove(c);
  }
  dbContext.Bs.Remove(b);
}
dbContext.As.Remove(someA);

解决了:


我首先使用数据库(sqlite)并在数据库端添加外键约束。

使用 vs2012 从 sqlite 数据库文件创建 edmx,

vs2012 未能设置关系的“on delete cascade”属性。

手动设置属性后,单次调用“dbContext.As.Remove(someA)”按预期工作!

4

1 回答 1

7

可悲的是,实体框架中(目前)没有批处理支持,所以你被foreach多个属性困住了。您可能想查看EntityFramework.Extended项目,它添加了各种批处理操作来整理这样的代码(以及提高性能)。

如果您确定在删除 A 时始终要删除相关的 B,则将此关系配置为使用“删除级联”行为。这意味着当父 A 被删除时,它的所有子 B 也会被自动删除。如何做到这一点取决于您如何创建数据库。如果您使用 Code First,它将是这样的:

public class MyContext : DbContext
{
    public DbSet<A> As { get; set; }
    public DbSet<B> Bs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
                    .HasMany(a => a.Bs)
                    .WithRequired(b => b.A)
                    .WillCascadeOnDelete();
    }
}
于 2013-08-08T09:52:54.720 回答