2012-12-14 3 views
2

Entity Framework (EF)를 사용하면 데이터베이스에서 개체를로드하고 수정 한 다음 다시 저장하려고합니다. 그러나로드 및 저장이 다른 컨텍스트에서 발생하고 개체의 컬렉션 속성에 다른 개체를 추가하여 개체를 수정합니다. 나는 100 Post의 1 Blog 개체가 내 데이터베이스에서다른 컨텍스트에서 엔티티 개체를로드/수정/저장하는 방법?

Blog blog; 

using (BloggingContext db = new BloggingContext()) 
{ 
    blog = db.Blogs.Include("Posts").Single(); 
} 

// No one else knows the `post` object directly. 
{ 
    Post post = new Post {Blog = blog, Title = "Title", Content = "Content"}; 
    blog.Posts.Add(post); 
} 

using (BloggingContext db = new BloggingContext()) 
{ 
    // No idea what I have to do before saving... 
    // Can't do anything with `post` here, since this part will not know this 
    // object directly. 

    //db.Blogs.Attach(blog); // throws an InvalidOperationException 
    db.SaveChanges(); 
} 

:

은 다음 MSDN에서 famous blog/posts example에 따라 코드를 살펴 보자. 보시다시피이 Blog에 새 Post을 추가하고 싶습니다. 아쉽게도 db.Blogs.Attach(blog);을 저장하기 전에 InvalidOperationException : "참조 무결성 제약 조건 위반이 발생했습니다 : 참조 제약 조건을 정의하는 속성 값이 관계의 주체 및 종속 개체간에 일치하지 않습니다."라는 메시지가 나타납니다.

EF에서이 블로그를 업데이트하려면 어떻게해야합니까?


는 UPDATE :

나는 (수정 및 관련 하위 개체에서 개체의 데이터베이스 업데이트 디커플링) 달성하려고 수 없습니다 무슨 생각합니다. 대신, 나는 부모 개체에서 하위 엔티티의 업데이트/생성을 분리하는 반대 방향을 더 실현 가능한 것으로 생각한다. 이것은 다음과 같은 방법을 수행 할 수 있습니다

Blog blog; 

using (BloggingContext db = new BloggingContext()) 
{ 
    blog = db.Blogs.Single(); 
} 

Post post = new Post {BlogId = blog.BlogId, Title = "Title", Content = "..."}; 

using (BloggingContext db = new BloggingContext()) 
{ 
    db.Posts.Add(post); 
    db.SaveChanges(); 
} 

답변

2

당신은 킥과 나머지를 할 것입니다 변경 사항을 저장해야 추적을 변경 한 다음 컨텍스트에 엔티티를 첨부해야합니다. 참고로

: MSDN Attach Entities to Context


를 또는 명시 적으로 추가하는 시도하고 관계가 있으므로 같은 탐색 속성을 통해 직접 아니라 필요한 정보를 설정합니다

Blog blog; 

using (BloggingContext db = new BloggingContext()) 
{ 
    blog = db.Blogs.Include("Posts").Single(); 

    Post post = new Post {Blog = blog, Title = "Title", Content = "Content"}; 
    post.blogId = blog.Id;  

    db.Posts.Add(post); 
    db.SaveChanges(); 
} 
+0

블로그를'db.Blogs '로 두 번째 컨텍스트에 첨부 할 때.첨부 (블로그);'InvalidOperationException'이 발생했습니다 : * 참조 무결성 제약 조건 위반이 발생했습니다 : 참조 제약 조건을 정의하는 속성 값이 관계에있는 주체 및 종속 개체간에 일치하지 않습니다 *. 게시 한 링크는 막연하게 관련되어 있습니다. –

+0

그런 다음 "어려운"방법을 시도해보십시오. 블로그는 게시물과 일대 다 관계를 맺습니다. 그러면 게시물에는 부모임을 알기 위해 blogId와 같은 필드가 포함됩니다. 그런 다음 블로그의 탐색 속성 모음에 게시물을 추가하는 대신 해당 ID를 설정하고 두 번째 컨텍스트 범위에서 명시 적으로 추가 작업을 수행하십시오. – dutzu

+0

이것은 다소 효과가 있지만 두 번째'using' 문에서'post'를 액세스 할 수있을 때에 만 작동합니다. 이것이 내가 피하려고하는 것이지만, 적절한 절충 일 수 있습니다. –

2

편집 3 :

모델 :

enter image description here

나는 이제 내 생각을 이해한다. 엔티티를 db 컨텍스트에 연결하고 상태를 올바르게 설정하는 방법.

문제는 블로그 인스턴스를 첨부 할 때 새로운 게시물과 기존 게시물 모음이 포함되어 있다는 것입니다. 해결 방법은 먼저 블로그 인스턴스의 얕은 사본을 첨부 (채워진 게시물 모음 제외) 한 다음 새 게시물을 추가하는 것입니다. changetracker에 기존 인스턴스를로드 할 수도 있지만 데이터베이스에 대한 왕복이 발생하고 일부 SO 비평가가 파티에 참여하게됩니다.

b.tw 나는 처음에 올바른 버전의 EF를 사용하고 정정 코드를 추가하기 전에 문제를 재현했습니다.

 public partial class Form1 : Form { 
      public Form1() { 
       InitializeComponent(); 
      } 

      Blog blog; 

      private void fetchBlogData_Click(object sender, EventArgs e) { 
       using (var db = new StackOverflowEntities()) { 

        blog = db.Set<Blog>().Include("Posts") 
         .FirstOrDefault(); 

       } 
      } 

      private void commitAllPosts_Click(object sender, EventArgs e) { 

       using (var db = new StackOverflowEntities()) { 

        // load existing blog into ChangeTracker (but not efficient) 
        // var existingBlog = db.Set<Blog>().First(b => b.BlogId == blog.BlogId); 

        // make shallow copy of existing blog and attach it 
        Blog existingBlog = new Blog { 
         BlogId = blog.BlogId, 
         Name = blog.Name 
        }; 

        db.Set<Blog>().Attach(existingBlog); 

        // if the root blog record must be updated 
        //db.Entry(existingBlog).State == EntityState.Modified; 

        // add new posts to tracked Blog entity 
        foreach (var post in blog.Posts) { 
         if (post.PostId == 0) { 
          existingBlog.Posts.Add(post); 
         } 
        }      

        db.SaveChanges(); 
       } 

      } 

      private void createArbPosts_Click(object sender, EventArgs e) { 
       var post = new Post { 

        Text = "Today I read but never understood a StackOverflow question.... again." 
       }; 

       blog.Posts.Add(post); 

       var postPS = new Post { 

        Text = "Actually, i'm not sure i understand it yet." 
       }; 

       blog.Posts.Add(postPS); 
      } 

     } 
+0

'db.Attach()'가 존재하지 않습니다. 하지만'db.Blogs.Attach()'는 그렇게합니다. 그러나 두 번째'using' 문에서'post'를 사용하여 아무 것도하고 싶지 않습니다. 저장을 할 클래스는'blog'에 정확히 어떤 일이 일어 났는지를 모릅니다. 그것은 단지 무언가가 일어나서 업데이트가 필요하다는 것을 알고 있습니다. EF가 어떻게 든 나머지를 알아낼 수 있기를 바랍니다. 그에 따라 내 질문을 명확히하겠습니다. –

+0

노력해 주셔서 감사합니다. 그러나 문제는 동일하게 유지됩니다. 업데이트 코드는 새로 생성되고 추가 된'Post' 객체를 알아야합니다. 업데이트 된'Blog' 객체 만 알고 싶습니다. 그렇지 않으면 사용자가했던 모든 변경 사항을 코드에서 '블로그'로 다시 생성해야합니다. –

+0

그래, 나는 그 질문에 대해 오해했다. 내 편집을 참조하십시오. 해결 방법은 먼저 블로그 인스턴스의 간단한 복사본을 추가 한 다음 새 게시물을 추가하는 것입니다. –

관련 문제