多对多- SaveChanges()实体框架4.1的问题



我在保存更改到数据库时遇到问题。

我正在更新我的控制器中的模型A,但是当我使用SaveChanges()保存更改时,我最终在数据库中为b创建了一个重复的项目

在UpdateModel()被调用后,我检查了b属性,正如我所期望的那样,但是在SaveChanges()被调用后,如果我检查了b属性,我会看到Id完全不同(新Id和新条目)。

我的类是这样的:

public class A
{
    [HiddenInput(DisplayValue = false)]
    public int AId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<B> Bs{ get; set; }
}
public class B
{
    [HiddenInput(DisplayValue = false)]
    public int BId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<A> As{ get; set; }
}

我的控制器是这样的:

    [HttpPost]
    public ActionResult Edit(A theA)
    {
        try
        {
           db.Entry(theA).State = EntityState.Modified;
           foreach (var item in theA.Bs)
           {
               db.Entry(item).State = EntityState.Modified;
           }
           db.SaveChanges();
           return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

我做错了什么吗?

Thanks in advance

这是常见的行为。问题是EF不知道您附加了一个现有的B,所以它会自动插入一个新记录。您必须通过调用

来说明B是存在的。
// here add B to the collection in the A and after that call:
dbContext.Entry<B>(someB).State = EntityState.Unchanged();

或通过附加B,然后将其添加到A集合(我不确定在ASP中使用UpdateModel时是否可能)。净MVC)。

dbContext.Bs.Attach(someB);
// now add B to the collection in the A

另一种可能性是先从数据库加载B,然后将加载的对象添加到A的集合中,但这需要额外的数据库往返。

int id = someB.Id;
var loadedB = dbCotnext.Bs.Single(b => b.Id == id);
someA.Bs.Add(loadedB);
dbContext.As.Add(someA);
dbContext.SaveChanges();

结论:每次调用Add时,整个对象图被跟踪为插入,除非你首先附加相关实体(在你将它们添加到插入的父元素之前-第二个和第三个例子),或者除非你在添加父元素后手动将相关实体的状态更改回不变。(第一个例子)。

最新更新