tl; dr:我有一些具有多对多关系的数据库。当我编辑其数据并调用SaveChanges()
时,数据库中没有任何更改。
完整问题:
我遇到了一个非常奇怪的问题。我想更新多对多关系,但它并不想改变。
我的模特看起来像这样(我只发布了这个问题中很重要的部分):
public class Note
{
public Note()
{
NoteTags = new HashSet<NoteTag>()
}
public int NoteId { get; set; }
public virtual ICollection<NoteTag> NoteTags { get; set; }
[...]
}
public class NoteTag
{
public int NoteId { get; set; }
public Note Note { get; set; }
public int TagId { get; set; }
public Tag Tag { get; set; }
}
public class Tag
{
public Tag()
{
NoteTags = new HashSet<NoteTag>();
}
public int TagId { get; set; }
public string Name { get; set; }
public virtual ICollection<NoteTag> NoteTags { get; set; }
[...]
}
我如何更新此数据库关系:
从数据库中获取当前状态Note
:
Note noteInDb = db.Notes.Include(x => x.NoteTags).ThenInclude(x => x.Tag).AsNoTracking().FirstOrDefault(x => x.NoteId == note.NoteId);
清除List<NoteTags>
并添加一个新的:
noteInDb.NoteTags = new List<NoteTag>();
noteInDb = TagsToAddToTags(note);
TagsToAddToTags
做了什么:它在数据库中找到合适的Tags
并将其添加到List<>
中,如下所示:
note.NoteTags.Add(new NoteTag { Tag = tagInDb });
然后我告诉数据库我已经修改了一些数据并保存了它:
db.Entry(noteInDb).State = EntityState.Modified;
db.SaveChanges();
当我将noteInDb
变量保存到数据库中时,Note noteInDb2 = db.Notes.Include(x=>x.NoteTags).ThenInclude(x=>x.Tag).FirstOrDefault(x => x.NoteId == note.NoteId);
变量看起来就像我想要的那样。 很遗憾没有保存任何东西,当我查看数据库时,它看起来仍然和以前一样。
奇怪的是,当我在SaveChanges()之后写这行时:
noteInDb2
我可以看到NoteTag
有9个NoteTag
s(它之前有4个,我希望它有5个,所以这实际上是以前的内容和我想要的内容的总和加上)。但是当我去LINQPad看看它的真实情况时,它会显示我4个 <?php
// Set the content-type
header('Content-Type: image/png');
// Create the image
$im = imagecreatetruecolor(400, 30);
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
// The text to draw
$text = 'Testing...';
// Replace path by your own font path
$font = 'arial.ttf';
// Add some shadow to the text
imagettftext($im, 20, 0, 11, 21, $grey, $font, $text);
// Add the text
imagettftext($im, 20, 0, 10, 20, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
?>
s(没有变化)。
我做错了什么?
答案 0 :(得分:2)
您可以使用此扩展程序删除未选择的项目,并将新选择的项目添加到列表中:
sp
使用它看起来像这样:
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);
}
答案 1 :(得分:0)
我认为您需要移动代码。由于使用AsNoTracking检索数据,因此在将实体的状态设置为已修改之前,不会跟踪更改。因此,在调用TagsToAddToTags之前,请调用db.Entry(noteInDb).State = EntityState.Modified;