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