EF 4.1 Code First:触发多对多更新

时间:2011-07-06 01:44:20

标签: entity-framework-4.1

我有一个实体BusinessUnit,它与Contact实体有多对多的关系。我们按照以下示例使用Fluent配置:

public BusinessUnitConfiguration()
{
    HasMany(c => c.Contacts)
        .WithMany()
        .Map(m =>
            {
                m.ToTable("BusinessUnitContact");
                m.MapLeftKey("BusinessUnitId");
                m.MapRightKey("ContactId");
            });

    ToTable("BusinessUnit");
}

public ContactConfiguration()
{
    ToTable("Contact");
}   

联络实体不知道它可能与哪些父母有关。我们正在使用Silverlight + WCF,因此禁用了延迟加载和代理创建。

我们在客户端上创建或修改一个对象图,该对象图包含一个BusinessUnit实例和零个或多个Contact实例,然后发送到WCF服务进行保存,创建新的上下文,并在必要时添加/附加/删除保存更改。

问题是,如果我在现有业务部门的Contacts集合中添加新联系人,EF不会插入联结记录 - 它知道要添加新联系人,因为我已经添加了它,但没有添加BusinessUnitContact将业务单位映射到联系人的行。

BusinessUnit上的Contacts属性是ObservableCollection< Contact>。它在添加父业务单位时有效,但在附加父业务单位时无效。

有什么方法可以告诉EF在将它附加到上下文时修改Contacts关联,这样就可以计算出需要插入哪些新的联结记录?

1 个答案:

答案 0 :(得分:0)

我发现了问题。将父实体附加到EF上下文的代码实际上并没有直接附加它 - 它正在加载原始实体,然后合并来自附加实体的属性:

// attach entity
var existing = GetQuery<TEntity>().FirstOrDefault(e => e.Id == entity.Id);
if (existing == null)
{
   throw new InvalidOperationException("Cannot attach an entity that does not exist in the database.");
}

switch (entity.State)
{
    case ObjectState.Modified:
        GetEntry(existing).CurrentValues.SetValues(entity);
        break;

    case ObjectState.Deleted:
        GetEntry(existing).State = EntityState.Deleted;
        break;
}

这似乎不适用于导航属性,因此我将代码更改为以下内容:

var set = GetSet<TEntity>();
set.Attach(entity);

// map object state to entity state
switch (entity.State)
{
    case ObjectState.Modified:
        GetEntry(entity).State = EntityState.Modified;
        break;

    case ObjectState.Deleted:
        GetEntry(entity).State = EntityState.Deleted;
        break;
}

所有需要改变的是确保附加的实体与进入的实体相同 - 也不必修改BusinessUnit实体。