EF 4.1代码优先SQL ce 4.0更新集合异常

Fra*_*sco 5 ef-code-first sql-server-ce-4 entity-framework-4.1

我首先在SQL ce 4.0中使用EF 4.1代码

我有两节课

public class Customer
{
    public int ID { get; set; }

    public string CompanyName { get; set; }

    public List<ContactPerson> ContactPersons { get; set; }
}

public class ContactPerson
{
    public int ID { get; set; }

    public string Name { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

和DbContext

public class MyDB : DbContext
{
    public DbSet<ContactPerson> ContactPersons { get; set; }

    public DbSet<Customer> Customers { get; set; }

    public MyDB()
    {
        this.Configuration.LazyLoadingEnabled = true;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>()
            .HasMany(c => c.ContactPersons)
            .WithRequired()
            .WillCascadeOnDelete(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

同时在代码中我需要更新客户的整个ContactPerson集合.

List<ContactPersons> modifiedContactPersons;
Customer customer = MyDB.Customers.Find(ID);
customer.ContactPersons = modifiedContactPersons;
Run Code Online (Sandbox Code Playgroud)

当我调用MyDB.SaveChanges()时,我得到以下异常:

保存不公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源.通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常.有关详细信息,请参阅InnerException.

与InnerException:

来自'Customer_ContactPersons'AssociationSet的关系处于'已删除'状态.给定多重约束,相应的'Customer_ContactPersons_Target'也必须处于'已删除'状态.

我明白这意味着什么,但我不能自己解决问题.有什么建议?

Lad*_*nka 8

这里的问题是:

customer.ContactPersons = modifiedContactPersons;
Run Code Online (Sandbox Code Playgroud)

它用新的相关联系人名单替换旧的相关联系人名单,并进行两项操作:

  • 它首先标记与所有以前相关的人的关系 Deleted
  • 然后它附上所有新的合同人员并标记与他们的关系 Added

第一个操作是一个问题,因为删除关系不会删除相关实体,因此您最终ContactPerson与任何内容无关,Customer并且您的映射不允许它(FK不可为空).

解决此问题取决于您尝试实现的要求.如果您确实要首先删除所有相关人员,则必须在分配新列表之前手动将每个人员的状态设置为已删除.如果您想更新现有人员,则根本不应该这样做.您应该迭代与客户相关的人员并从新列表中修改他们的数据.为什么?因为:

  • 如果你删除实体并插入一个新实体而不是更新现有实体,你将有两个数据库修改语句而不是一个=两个往返数据库而不是一个,如果有很多实体,它会大大减慢你的应用程序
  • 如果您有任何其他依赖的实体,ContractPerson则无法将其删除.此外,如果您ContractPersonId某处使用它并且如果它是自动生成的,则在删除原始记录后它将不再存在.
  • 这通常是非常错误和懒惰的方法.插入新记录,修改现有记录并仅删除应该删除的记录.