Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
Asp.net 如何更新实体框架7中的多对多关系?_Asp.net_Entity Framework_Entity Framework Core - Fatal编程技术网

Asp.net 如何更新实体框架7中的多对多关系?

Asp.net 如何更新实体框架7中的多对多关系?,asp.net,entity-framework,entity-framework-core,Asp.net,Entity Framework,Entity Framework Core,tl;dr:我有一个多对多关系的数据库。当我编辑其数据并调用SaveChanges()时,数据库中没有任何更改 完整问题: 我遇到了一个非常奇怪的问题。我想更新多对多关系,但它不想改变 我的模型是这样的(我只发布了这个问题中重要的部分): 清除列表并添加新列表: noteInDb.NoteTags = new List<NoteTag>(); noteInDb = TagsToAddToTags(note); 然后我告诉数据库我修改了一些数据并保存了它: db.Entry(note

tl;dr:我有一个多对多关系的数据库。当我编辑其数据并调用
SaveChanges()
时,数据库中没有任何更改

完整问题:

我遇到了一个非常奇怪的问题。我想更新多对多关系,但它不想改变

我的模型是这样的(我只发布了这个问题中重要的部分):

清除
列表
并添加新列表:

noteInDb.NoteTags = new List<NoteTag>();
noteInDb = TagsToAddToTags(note);
然后我告诉数据库我修改了一些数据并保存了它:

db.Entry(noteInDb).State = EntityState.Modified;
db.SaveChanges();
noteInDb
变量在将其保存到数据库时的外观与我希望的完全相同不幸的是,没有保存任何内容,当我查看数据库时,它看起来仍然与以前一样。

奇怪的是,当我在SaveChanges()之后写这一行时:

我可以看到
noteInDb2
有9个
NoteTag
s(它以前有4个,我希望它有5个,所以这实际上是以前的和我想添加的内容的总和)。但当我去LINQPad查看它的真实外观时,它会显示4个旧的
NoteTag
s(无更改)


我做错了什么?

我认为您需要移动代码。由于使用AsNoTracking检索数据,因此在将实体的状态设置为“已修改”之前,不会跟踪更改。因此,在调用TagsToAddToTags之前,先调用db.Entry(noteInDb.State=EntityState.Modified

您可以使用我所做的扩展来删除未选中的项目,并将新选中的项目添加到列表中:

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);
}

嗯,它还是不起作用。在调用SaveChanges时,我是否可以检查数据实体框架将要更改的内容?EF是否将正在对数据库执行的查询保存在某个地方?这会有很大帮助,因为我不知道调用SaveChanges()时EF到底在做什么。您可以通过添加跟踪提供程序来跟踪查询,但也可以在SQL Server profiler中轻松地跟踪查询。您可以在添加实体后检查它们的状态,这可能是最好的起点。db.Entry(newNoteTag)。在触发保存更改之前声明。
note.NoteTags.Add(new NoteTag { Tag = tagInDb });
db.Entry(noteInDb).State = EntityState.Modified;
db.SaveChanges();
Note noteInDb2 = db.Notes.Include(x=>x.NoteTags).ThenInclude(x=>x.Tag).FirstOrDefault(x => x.NoteId == note.NoteId);
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.Notes
    .Include(x => x.NoteTags)
    .FirstOrDefault(x => x.NoteId == note.NoteId);

db.TryUpdateManyToMany(model.NoteTags, listOfNewTagIds
.Select(x => new NoteTag
{
    TagId = x,
    NoteId = note.NoteId
}), x => x.TagId);