EF7의 탐색 속성 업데이트가 저장되지 않습니다.

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

및 DbContext (관련이있는 경우이 프로젝트에서 ASP.NET ID를 사용합니다).

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

마이그레이션 (SQL Server) 후에는 데이터베이스 테이블이 예상대로 표시됩니다. Post 테이블에 ResourceId에 대한 외부 키가 있습니다.

게시물의 작품을 만드는 것은 post.Resource (이미 생성 된 자원)를 첨부 할 때 잘 동작합니다.

post.Resource를 대체하려고 할 때 내 문제가 발생합니다 . 대체 (replace) 란 이미 기존의 리소스 중 하나를 선택하여 게시에 할당하는 것을 의미합니다.

var resource2 = Database.Resources.First(r=>r.Url == "xyz");

나는 시도했다 :

  1. post.Resource = resource2; Database.Entry(post).State = EntityState.Modified;

  2. Database.Entry(post).Property(p => p.Resource).CurrentValue = resource2;

  3. post.Resource = null;

그 (것)들의 다른 조합으로 또한 , 그러나 그들 모두는 작동하지 않는다. 호출 후 await SaveChangesAsync(); 데이터베이스에서 검색하면 변경 사항이 없습니다. 바꾸기 (외래 키 업데이트)를 올바르게 수행하는 방법은 무엇입니까?

// 14.09.2015 업데이트 추가 선택에 의해 문제가 발생하여 일대 다 관계를 업데이트했습니다. 전체 코드 :

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

수락 된 답변

나는 이것이 Eager Loading 과 관련이 있다고 생각했지만, AspNet.Identity 유무에 AspNet.Identity 없이 문제를 재현 할 수는 없습니다. 아래의 코드를 실행하면 리소스가 항상 업데이트됩니다. EntityFramework 7.0.0-beta7 .

암호

static void Main(string[] args)
{
    Init();
    WithEagerLoading();
    CleanUp();

    Init();
    WithoutEagerLoading();
    CleanUp();
}

private static void WithoutEagerLoading()
{
    var db = new MyContext();
    var post = db.Posts.First(); // no eager loading of child
    post.Resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    db.SaveChanges();

    Console.WriteLine($"2nd Resource.Id: {new MyContext().Posts.Include(p => p.Resource).First().Resource.Id}");
}

private static void WithEagerLoading()
{
    var db = new MyContext();
    var post = db.Posts
        .Include(p => p.Resource) // eager loading
        .First();
    post.Resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    db.SaveChanges();

    Console.WriteLine($"2nd Resource.Id: {new MyContext().Posts.Include(p => p.Resource).First().Resource.Id}");
}

private static void CleanUp()
{
    var db = new MyContext();
    db.Posts.RemoveRange(db.Posts);
    db.Resources.RemoveRange(db.Resources);
    db.SaveChanges();
}

private static void Init()
{
    var db = new MyContext();
    var resource = new Resource { Url = "http://atqu.in" };
    var resource2 = new Resource { Url = "http://trend.atqu.in" };
    var post = new Post { Resource = resource };
    db.Add(post);
    db.Add(resource);
    db.Add(resource2);
    db.SaveChanges();

    db = new MyContext();
    post = db.Posts.Include(p => p.Resource).First();
    resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    Console.WriteLine($"1st Resource.Id: {post.Resource.Id}");
}

결과

static void Main(string[] args)
{
    Init();
    WithEagerLoading();
    CleanUp();

    Init();
    WithoutEagerLoading();
    CleanUp();
}

private static void WithoutEagerLoading()
{
    var db = new MyContext();
    var post = db.Posts.First(); // no eager loading of child
    post.Resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    db.SaveChanges();

    Console.WriteLine($"2nd Resource.Id: {new MyContext().Posts.Include(p => p.Resource).First().Resource.Id}");
}

private static void WithEagerLoading()
{
    var db = new MyContext();
    var post = db.Posts
        .Include(p => p.Resource) // eager loading
        .First();
    post.Resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    db.SaveChanges();

    Console.WriteLine($"2nd Resource.Id: {new MyContext().Posts.Include(p => p.Resource).First().Resource.Id}");
}

private static void CleanUp()
{
    var db = new MyContext();
    db.Posts.RemoveRange(db.Posts);
    db.Resources.RemoveRange(db.Resources);
    db.SaveChanges();
}

private static void Init()
{
    var db = new MyContext();
    var resource = new Resource { Url = "http://atqu.in" };
    var resource2 = new Resource { Url = "http://trend.atqu.in" };
    var post = new Post { Resource = resource };
    db.Add(post);
    db.Add(resource);
    db.Add(resource2);
    db.SaveChanges();

    db = new MyContext();
    post = db.Posts.Include(p => p.Resource).First();
    resource = db.Resources.First(p => p.Url == "http://trend.atqu.in");
    Console.WriteLine($"1st Resource.Id: {post.Resource.Id}");
}

16/9 편집

편집 된 질문 코드의 문제는 post 을 검색 한 후에 Database 를 인스턴스화하기 때문입니다. postDatabase 인스턴스에 연결되어 있지 않으므로 Resource 를 첨부하고 SaveChangesAsync 호출하면 아무 것도하지 않습니다. 그 시점의 post 은 저장중인 Database 와 관련이 있기 때문입니다. 그래서 post 포스트를 다시 선택하게되면 (인스턴스 생성 후에) post 가 고정되게됩니다. 그러면 post 의 인스턴스가 첨부되기 때문입니다. post 다시 선택하지 않으려면 동일한 DbContext 인스턴스를 사용하여 원래 post 검색하는 데 사용한 작업을 수행해야합니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.