2017-03-24 56 views
6

我们正在将我们现有的MVC6 EF6应用程序移植到核心。实体框架核心更新多对多

在EF核心中有一个简单的方法来更新多对多的关系吗?

我从EF6的旧代码,我们清除列表并用新数据覆盖它,不再有效。

  var model = await _db.Products.FindAsync(vm.Product.ProductId); 

      model.Colors.Clear(); 

      model.Colors = _db.Colors.Where(x => 
      vm.ColorsSelected.Contains(x.ColorId)).ToList(); 

回答

11

这将适用于你。

做一个类有

public class ColorProduct 
{ 
    public int ProductId { get; set; } 
    public int ColorId { get; set; } 

    public Color Color { get; set; } 
    public Product Product { get; set; } 
} 

的关系添加ColorProduct收集到你的产品和Color类

public ICollection<ColorProduct> ColorProducts { get; set; } 

然后使用这个扩展我做了,除去未选中并添加新已入选列表

public static void TryUpdateManyToMany<T, TKey>(this DbContext db, IEnumerable<T> currentItems, IEnumerable<T> newItems, Func<T, TKey> getKey) where T : class 
    { 
     db.Set<T>().RemoveRange(currentItems.Except(newItems, getKey)); 
     db.Set<T>().AddRange(newItems.Except(currentItems, getKey)); 
    } 

    public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKeyFunc) 
    { 
     return items 
      .GroupJoin(other, getKeyFunc, getKeyFunc, (item, tempItems) => new { item, tempItems }) 
      .SelectMany(t => t.tempItems.DefaultIfEmpty(), (t, temp) => new { t, temp }) 
      .Where(t => ReferenceEquals(null, t.temp) || t.temp.Equals(default(T))) 
      .Select(t => t.t.item); 
    } 

使用它看起来像这样

var model = _db.Products 
      .Include(x => x.ColorProducts) 
      .FirstOrDefault(x => x.ProductId == vm.Product.ProductId); 

_db.TryUpdateManyToMany(model.ColorProducts, vm.ColorsSelected 
.Select(x => new ColorProduct 
{ 
    ColorId = x, 
    ProductId = vm.Product.ProductId 
}), x => x.ColorId); 
+0

哇,这太神奇了。我可以在我的所有项目中使用此扩展。感谢您的及时答复。 –

+0

该解决方案的关键部分(以及OP代码中的问题)是“Include”调用。 –

+1

'除了延长是惊人的,谢谢。 –