5

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

我有两节课

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; }

}

和一个 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);
    }
}

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

List<ContactPersons> modifiedContactPersons;
Customer customer = MyDB.Customers.Find(ID);
customer.ContactPersons = modifiedContactPersons;

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

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

带有内部异常:

来自“Customer_ContactPersons”关联集的关系处于“已删除”状态。给定多重约束,相应的“Customer_ContactPersons_Target”也必须处于“已删除”状态。

我明白这意味着什么,但我无法自己解决问题。有什么建议么?

4

1 回答 1

8

这里的问题是:

customer.ContactPersons = modifiedContactPersons;

它将旧的相关联系人列表替换为新的相关联系人列表,它执行两个操作:

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

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

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

  • 如果您删除实体并插入一个新实体而不是更新现有实体,您将有两个数据库修改语句而不是一个 = 两次到数据库的往返而不是一个,如果实体很多,它会大大降低您的应用程序
  • 如果您有任何其他依赖于ContractPerson您的实体,则无法将其删除。此外,如果您在某处使用ContractPerson'sId并且它是自动生成的,则在您删除原始记录后它将不再存在。
  • 这通常是非常错误和懒惰的方法。插入新记录,修改现有记录,只删除真正应该删除的记录。
于 2011-07-19T09:58:46.660 回答