Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 实体框架核心多对多更新_Entity Framework_Asp.net Core - Fatal编程技术网

Entity framework 实体框架核心多对多更新

Entity framework 实体框架核心多对多更新,entity-framework,asp.net-core,Entity Framework,Asp.net Core,我们正在将现有的MVC6 EF6应用程序移植到Core EF Core中是否有更新多对多关系的简单方法 我的旧代码来自EF6,在那里我们清除列表并用新数据覆盖它不再工作 var model = await _db.Products.FindAsync(vm.Product.ProductId); model.Colors.Clear(); model.Colors = _db.Colors.Where(x => vm.ColorsSelected.Contains(x.ColorId)

我们正在将现有的MVC6 EF6应用程序移植到Core

EF Core中是否有更新多对多关系的简单方法

我的旧代码来自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();

这对你有用

创建一个类以在其中建立关系:

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

    public Color Color { get; set; }
    public Product Product { get; set; }
}
ColorProduct
集合添加到您的
Product
Color
类中:

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

为了避免上述答案中的LINQ地狱,模板化的“Except”方法可以重写为:

public static IEnumerable<TEntity> LeftComplementRight<TEntity, TKey>(
        this IEnumerable<TEntity> left,
        IEnumerable<TEntity> right,
        Func<TEntity, TKey> keyRetrievalFunction)
    {
        var leftSet = left.ToList();
        var rightSet = right.ToList();

        var leftSetKeys = leftSet.Select(keyRetrievalFunction);
        var rightSetKeys = rightSet.Select(keyRetrievalFunction);

        var deltaKeys = leftSetKeys.Except(rightSetKeys);
        var leftComplementRightSet = leftSet.Where(i => deltaKeys.Contains(keyRetrievalFunction.Invoke(i)));
        return leftComplementRightSet;
    }
公共静态IEnumerable leftright(
这是一个数不清的左边,
我数不清的权利,
Func键检索函数)
{
var leftSet=left.ToList();
var rightSet=right.ToList();
var leftSetKeys=leftSet.Select(keyRetrievalFunction);
var rightSetKeys=righset.Select(keyRetrievalFunction);
var deltaKeys=左设置键。除(右设置键)外;
var leftcomplementrighset=leftSet.Where(i=>deltaKeys.Contains(keyRetrievalFunction.Invoke(i));
返回leftrighset;
}
此外,可以更新UpdateManyToMany方法,以包括已修改的实体:

public void UpdateManyToMany<TDependentEntity, TKey>(
        IEnumerable<TDependentEntity> dbEntries,
        IEnumerable<TDependentEntity> updatedEntries,
        Func<TDependentEntity, TKey> keyRetrievalFunction)
        where TDependentEntity : class
    {
        var oldItems = dbEntries.ToList();
        var newItems = updatedEntries.ToList();
        var toBeRemoved = oldItems.LeftComplementRight(newItems, keyRetrievalFunction);
        var toBeAdded = newItems.LeftComplementRight(oldItems, keyRetrievalFunction);
        var toBeUpdated = oldItems.Intersect(newItems, keyRetrievalFunction);

        this.Context.Set<TDependentEntity>().RemoveRange(toBeRemoved);
        this.Context.Set<TDependentEntity>().AddRange(toBeAdded);
        foreach (var entity in toBeUpdated)
        {
            var changed = newItems.Single(i => keyRetrievalFunction.Invoke(i).Equals(keyRetrievalFunction.Invoke(entity)));
            this.Context.Entry(entity).CurrentValues.SetValues(changed);
        }
    }
public void updatemanytomy(
IEnumerable dbEntries,
i无数次的尝试,
Func键检索函数)
其中TDependentity:类
{
var oldItems=dbEntries.ToList();
var newItems=updatedEntries.ToList();
var toBeRemoved=oldItems.LeftComplementRight(newItems,keyRetrievalFunction);
var tobeaded=newItems.LeftComplementRight(oldItems,keyRetrievalFunction);
var toBeUpdated=oldItems.Intersect(newItems,keyRetrievalFunction);
this.Context.Set();
this.Context.Set().AddRange(tobedded);
foreach(待更新的var实体)
{
var changed=newItems.Single(i=>keyRetrievalFunction.Invoke(i).Equals(keyRetrievalFunction.Invoke(entity));
this.Context.Entry(entity).CurrentValues.SetValues(已更改);
}
}
它使用另一个自定义模板“Intersect”函数来查找两个集合的交点:

public static IEnumerable<TEntity> Intersect<TEntity, TKey>(
        this IEnumerable<TEntity> left,
        IEnumerable<TEntity> right,
        Func<TEntity, TKey> keyRetrievalFunction)
    {
        var leftSet = left.ToList();
        var rightSet = right.ToList();

        var leftSetKeys = leftSet.Select(keyRetrievalFunction);
        var rightSetKeys = rightSet.Select(keyRetrievalFunction);

        var intersectKeys = leftSetKeys.Intersect(rightSetKeys);
        var intersectionEntities = leftSet.Where(i => intersectKeys.Contains(keyRetrievalFunction.Invoke(i)));
        return intersectionEntities;
    }
公共静态IEnumerable Intersect(
这是一个数不清的左边,
我数不清的权利,
Func键检索函数)
{
var leftSet=left.ToList();
var rightSet=right.ToList();
var leftSetKeys=leftSet.Select(keyRetrievalFunction);
var rightSetKeys=righset.Select(keyRetrievalFunction);
var intersectKeys=leftSetKeys.Intersect(rightSetKeys);
var intersectionenties=leftSet.Where(i=>intersectKeys.Contains(keyRetrievalFunction.Invoke(i));
返回交叉实体;
}

哇,这太棒了。我可以在我的所有项目中使用此扩展。感谢您及时的回答。此解决方案的关键部分(以及操作代码中的问题)是
Include
call.AddRange没有Func getKey参数这是一种好的有效方法吗?或者您是否找到了其他可能的方法?为什么要检查null和default是否相等?我想只有默认值才足够(因为ref类型的默认值可以为null)。什么是不再工作?它不再产生预期的结果。实体框架核心的更改跟踪方式有所不同。我遇到了类似的问题,尝试了下面的各种答案,最后通过确保对子集合调用了
Include()
thenclude()
Colors
)。简单得多。这篇文章也很有用:现在还不清楚“不再有效”是什么意思。如果关系的数量有限,并且可以使用EF core进行替换,那么替换关系是最简单的方法。
public void UpdateManyToMany<TDependentEntity, TKey>(
        IEnumerable<TDependentEntity> dbEntries,
        IEnumerable<TDependentEntity> updatedEntries,
        Func<TDependentEntity, TKey> keyRetrievalFunction)
        where TDependentEntity : class
    {
        var oldItems = dbEntries.ToList();
        var newItems = updatedEntries.ToList();
        var toBeRemoved = oldItems.LeftComplementRight(newItems, keyRetrievalFunction);
        var toBeAdded = newItems.LeftComplementRight(oldItems, keyRetrievalFunction);
        var toBeUpdated = oldItems.Intersect(newItems, keyRetrievalFunction);

        this.Context.Set<TDependentEntity>().RemoveRange(toBeRemoved);
        this.Context.Set<TDependentEntity>().AddRange(toBeAdded);
        foreach (var entity in toBeUpdated)
        {
            var changed = newItems.Single(i => keyRetrievalFunction.Invoke(i).Equals(keyRetrievalFunction.Invoke(entity)));
            this.Context.Entry(entity).CurrentValues.SetValues(changed);
        }
    }
public static IEnumerable<TEntity> Intersect<TEntity, TKey>(
        this IEnumerable<TEntity> left,
        IEnumerable<TEntity> right,
        Func<TEntity, TKey> keyRetrievalFunction)
    {
        var leftSet = left.ToList();
        var rightSet = right.ToList();

        var leftSetKeys = leftSet.Select(keyRetrievalFunction);
        var rightSetKeys = rightSet.Select(keyRetrievalFunction);

        var intersectKeys = leftSetKeys.Intersect(rightSetKeys);
        var intersectionEntities = leftSet.Where(i => intersectKeys.Contains(keyRetrievalFunction.Invoke(i)));
        return intersectionEntities;
    }