Asp.net core 未保存EF7中导航属性的更新
我有一个简单的模型:Asp.net core 未保存EF7中导航属性的更新,asp.net-core,entity-framework-core,Asp.net Core,Entity Framework Core,我有一个简单的模型: public class Post { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { set; get; } //non-important properties stripped, to focus on problem public virtual Resource Resource
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { set; get; }
//non-important properties stripped, to focus on problem
public virtual Resource Resource { set; get; }
public virtual ICollection<Tag> Tags { set; get; }
}
public class Resource
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { set; get; }
[Url]
public string Url { set; get; }
}
我认为这可能与快速加载有关,但是无论是否使用
AspNet.Identity
,我都无法重现您的问题。运行以下代码会导致资源始终处于更新状态。使用EntityFramework 7.0.0-beta7
代码
static void Main(字符串[]args)
{
Init();
加载();
清理();
Init();
WithOutagerLoading();
清理();
}
不带OutagerLoading()的私有静态void
{
var db=new MyContext();
var post=db.Posts.First();//不急于加载子对象
post.Resource=db.Resources.First(p=>p.Url==”http://trend.atqu.in");
db.SaveChanges();
WriteLine($“第二个Resource.Id:{new MyContext().Posts.Include(p=>p.Resource.First().Resource.Id}”);
}
私有静态void(带加载)
{
var db=new MyContext();
var post=db.Posts
.Include(p=>p.Resource)//立即加载
.First();
post.Resource=db.Resources.First(p=>p.Url==”http://trend.atqu.in");
db.SaveChanges();
WriteLine($“第二个Resource.Id:{new MyContext().Posts.Include(p=>p.Resource.First().Resource.Id}”);
}
私有静态无效清除()
{
var db=new MyContext();
配电柱拆除范围(配电柱);
db.Resources.RemoveRange(db.Resources);
db.SaveChanges();
}
私有静态void Init()
{
var db=new MyContext();
var资源=新资源{Url=”http://atqu.in" };
var resource2=新资源{Url=”http://trend.atqu.in" };
var post=new post{Resource=Resource};
db.Add(post);
db.Add(资源);
db.Add(资源2);
db.SaveChanges();
db=新的MyContext();
post=db.Posts.Include(p=>p.Resource.First();
resource=db.Resources.First(p=>p.Url==”http://trend.atqu.in");
WriteLine($“1st Resource.Id:{post.Resource.Id}”);
}
结果
1st Resource.Id: 0f4d222b-4184-4a4e-01d1-08d2bc9cea9b
2nd Resource.Id: 00ccae9c-f0da-43e6-01d2-08d2bc9cea9b
1st Resource.Id: 749f08f0-2426-4043-01d3-08d2bc9cea9b
2nd Resource.Id: 2e83b512-e8bd-4583-01d4-08d2bc9cea9b
编辑16/9
编辑的问题代码中的问题是因为您在检索
post
后正在实例化数据库post
未附加到数据库的该实例,因此当您将资源
附加到该实例并调用SaveChangesSync
时,它不会执行任何操作,因为那时post
与您要保存的数据库
没有任何关系。这就是为什么再次选择post
post(在实例化之后)的解决方法会导致它被修复的原因,因为这样会附加post
的实例。如果您不想再次选择post
,您应该使用与最初检索post
相同的DbContext
实例来执行上述工作,您如何创建post,以及如何填充post
?谢谢您的回答,但这不是我的情况。当您替换资源时,总是在创建新实例。在我的例子中,我有一些现有资源(设置了Id和Url),然后我想用一个现有资源替换post.Resource。它看起来像post.Resource=Context.Resources.First(r=>r.Url==“xyz”)。显然,我断言我试图分配的资源存在于数据库中。@MarcinZablocki我已更新了答案以附加现有的资源,但发现结果仍然相同-无法复制。我建议你把你所有的代码都贴出来。再次感谢。我更新了我的问题并指出了问题所在。我通过保存数据库,然后再次选择“发布”,然后再次分配资源并保存,解决了这个问题。@Marcin在您发布的代码中,它反映了问题,还是解决了问题?我将在下周检查它,我认为您的答案解决了这个问题;)
var Database new DbContext();
var resource2 = Database.Resources.First(r=>r.Url == "xyz");
var oldAssignedTags = Database.Posts.Include(p=>p.Tags).FirstOrDefault(p => p.Id == post.Id).Tags;
var tags = newTags as List<Tag> ?? newTags.ToList();
//TagComparer is irrelevant here
var toRemove = oldAssignedTags.Except(tags, TagComparer);
var toAdd = tags.Except(oldAssignedTags, TagComparer);
foreach (var tag in toRemove)
{
Database.Entry(tag).State = EntityState.Deleted; //Database.Tags.Remove(tag);
}
foreach (var tag in toAdd)
{
tag.Post = post;
post.Tags.Add(tag);
}
post.Resource = resource2;
await Database.SaveChangesAsync();
1st Resource.Id: 0f4d222b-4184-4a4e-01d1-08d2bc9cea9b
2nd Resource.Id: 00ccae9c-f0da-43e6-01d2-08d2bc9cea9b
1st Resource.Id: 749f08f0-2426-4043-01d3-08d2bc9cea9b
2nd Resource.Id: 2e83b512-e8bd-4583-01d4-08d2bc9cea9b