MVC POST 编辑示例

假设我们有一个具有多种颜色的 Product 类,可以在许多产品上使用。

public class Product
{       
    public int ProductId { get; set; }
    public ICollection<ColorProduct> ColorProducts { get; set; }
}

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

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

public class Color
{      
    public int ColorId { get; set; }
    public ICollection<ColorProduct> ColorProducts { get; set; }
}

使用此扩展程序可以更轻松:

public static class Extensions
{
    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);
    }
}

更新产品的颜色看起来像这样(MVC 编辑 POST 方法)

[HttpPost]
public IActionResult Edit(ProductVm vm)
{
if (ModelState.IsValid)
    {
        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);

        db.SaveChanges();

        return RedirectToAction("Index");
    }   
   return View(vm);
}

public class ProductVm
{          
    public Product Product { get; set; }
    
    public IEnumerable<int> ColorsSelected { get; set; }      
}

代码已尽可能简化,任何类都没有额外的属性。