我知道在SO上已多次询问过这个问题,但我找不到关于如何在EF CF中添加或更新导航属性的明确答案。
实体(简化):
public class Basket : EntityBase
{
public virtual List<Fruit> TaggedFruits { get; set; }
}
public class Fruit : EntityBase
{
}
的ActionResult:
[HttpPost]
public ActionResult SaveTags(Basket basket, int[] selectedFruits)
{
basket.TaggedFruits = new List<Fruits>();
foreach (int guid in selectedFruits)
basket.TaggedFruits.Add(repository.Fruits.FirstOrDefault(p => p.Id == guid));
using (var context = new EFDbContext())
{
context.Baskets.Attach(basket);
context.SaveChanges();
}
return RedirectToAction("GetBasket", new {guid = basket.Guid});
}
我已经尝试过上面的SaveTags方法的多次迭代,但从来没有让它工作。这个抛出:
IEntityChangeTracker的多个实例无法引用实体对象。
在研究了这里和其他网站之后,错误显然表明在方法中混合我的存储库模式和DBContext会导致冲突。
如果我使用以下方法将标记移动到存储库:
[HttpPost]
public ActionResult SaveTags(Basket basket, int[] selectedFruits)
{
List<Fruit> taggedFruits = new List<Fruit>();
foreach (int guid in selectedFruits)
taggedFruits.Add(new Fruit {Id = guid});
libraryRepository.TagBasket(basket, taggedFruits);
return RedirectToAction("GetBasket", new {guid = basket.Guid});
}
/*in repository*/
public void TagBasket(Basket basket, List<Fruit> fruits )
{
basket.Taggedfruits = new List<Fruit>();
foreach (var fruit in fruits)
{
basket.Taggedfruits.Add(Fruit);
}
context.Baskets.Attach(basket);
context.SaveChanges();
}
然后,不会对数据库进行任何更改。什么都没发生。有人能指出我正确的方向吗?我一直在争取这么长时间,谢谢......
答案 0 :(得分:5)
好吧,您只是将实体(=设置状态附加到Unchanged
)然后调用SaveChanges
。在这种情况下,你告诉EF没有任何改变 - &gt;没有任何反应。
要更改Basket
和TaggedFruits
之间的关系,您必须从数据库中加载购物篮的原始水果集合,然后从/向已加载的水果集合中删除或添加标记的水果根据您的Id集合中的ID提示:
public void TagBasket(Basket basket, List<Fruit> fruits)
{
var basketInDB = context.Baskets.Include(b => b.Taggedfruits)
.Single(b => b.Id == basket.Id);
foreach (var fruitInDB in basketInDB.Taggedfruits.ToList())
if (!fruits.Any(f => f.Id == fruitInDB.Id))
basketInDB.Taggedfruits.Remove(fruitInDB);
foreach (var fruit in fruits)
if (!basketInDB.Taggedfruits.Any(f => f.Id == fruit.Id))
{
var newFruit = new Fruit { Id = fruit.Id };
context.Fruits.Attach(newFruit);
basketInDB.TaggedFruits.Add(newFruit);
}
// Next line is only necessary if other properties in basket
// could have been changed in your view
context.Entry(basketInDB).CurrentValues.SetValues(basket);
context.SaveChanges();
}
您也可以将int[] selectedFruits
集合传入此方法,因为只需要ID。