EF4.1代码优先 - 如何分配/删除多对多?

时间:2011-07-12 15:50:50

标签: entity-framework many-to-many entity-framework-4.1

我在产品和产品组之间存在多对多的关系。

使用EF4.1 Code First,在向ProductGroup添加产品/从ProductGroup中删除产品时,我会得到奇怪且不存在的结果。

我的观点完美无缺;它重新调整GroupId和List productIds。问题出在控制器中,我遍历productIds列表并分配/删除到ProductGroup。

以下是我的代码摘录,用于从ProductGroup中删除产品:

    ProductGroup productGroup = _Repository.GetProductGroup(groupId);
    using (var db = GetDbContext())
    {

        foreach (var pId in productIds)
        {
            Product p = _Repository.GetProduct(Convert.ToInt32(pId));

            productGroup.Products.Remove(p);
            db.Entry(productGroup).State = System.Data.EntityState.Modified;

            p.ProductGroups.Remove(productGroup);
            db.Entry(p).State = System.Data.EntityState.Modified;

            db.SaveChanges();                       
        }
    }

基本上,我必须同时影响ProductGroup和单个产品以获得任何结果......然后结果是混合的。例如,在检查数据库表(ProductGroupProducts)时,只会删除一些记录,但我无法弄清楚哪些是哪种模式,哪些不是。

将产品分配到ProductGroup时遇到类似问题。代码几乎与明显的.Add()而不是.Remove()。

相同

我在这里缺少什么?有人知道这样做的更好,并且希望更一致吗?

非常感谢提前!

拉​​杜

1 个答案:

答案 0 :(得分:2)

什么是GetDbContext()?如果这创建了新的上下文,那么db显然是另一个上下文,而不是您在_Repository中使用的上下文。 (如果它返回与_Repository正在使用的相同的上下文,那么using块很奇怪,因为它在最后处理了上下文,因此也破坏了_Repository中的上下文。

您必须将productGroupp附加到您正在进行修改的上下文中:

ProductGroup productGroup = _Repository.GetProductGroup(groupId);
using (var db = GetDbContext())
{
    db.ProductGroups.Attach(productGroup);
    foreach (var pId in productIds)
    {
        Product p = _Repository.GetProduct(Convert.ToInt32(pId));
        db.Products.Attach(p);

        productGroup.Products.Remove(p);
    }
    db.SaveChanges();                       
}

我已删除p.ProductGroups.Remove(productGroup),因为我认为EF会在您从群组中删除产品时自动执行此操作(但我不确定;您可以在调试器中查看这些集合以查看。)

如果GetDbContext()确实创建了新的上下文,则重新考虑设计。您应该只有一个上下文用于此类操作(读取和更新)。

修改

这可能更容易:

ProductGroup productGroup = _Repository.GetProductGroup(groupId);
using (var db = GetDbContext())
{
    db.ProductGroups.Attach(productGroup);
    foreach (var pId in productIds)
    {
        var p = productGroup.Products
            .SingleOrDefault(p1 => p1.ID == Convert.ToInt32(pId))

        if (p != null)
            productGroup.Products.Remove(p);
    }
    db.SaveChanges();                       
}

它可以为您保存产品的数据库查询。我假设你要么使用延迟加载,要么_Repository.GetProductGroup对产品集合有Include