我知道这个问题已在 SO 上被多次询问,但我找不到有关如何在 EF CF 中添加或更新导航属性的明确答案。
实体(简化):
public class Basket : EntityBase
{
public virtual List<Fruit> TaggedFruits { get; set; }
}
public class Fruit : EntityBase
{
}
操作结果:
[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();
}
然后不会向数据库提交任何更改。根本什么也没发生。有人能指出我正确的方向吗?我已经为此奋斗了很长时间,谢谢......
最佳答案
好吧,您只需附加实体(= 将状态设置为Unchanged
),然后调用SaveChanges
。在这种情况下,您告诉 EF 没有任何改变 -> 没有发生任何事情。
要更改 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。
关于asp.net-mvc - 在 EF CF 中添加/更新导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10301127/