2

Entity Framework (EF) を使用して、データベースからオブジェクトを読み込み、変更して保存したいと考えています。ただし、読み込みと保存は異なるコンテキストで発生するため、別のオブジェクトをオブジェクトのコレクション プロパティに追加して変更します。

MSDNの有名なブログ/投稿の例に基づいて、次のコードを検討してください。

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

私のデータベースにはBlog、100 個のオブジェクトが 1 つありますPost。ご覧のとおり、Postこれに新しい を追加したいと思いBlogます。残念ながら、保存する前に次のことわざdb.Blogs.Attach(blog);をスローします。InvalidOperationException

EF がこのブログを更新できるようにするには、どうすればよいですか?


アップデート:

私が達成しようとしていたこと (エンティティのデータベース更新を変更とそれに関連する子エンティティから分離すること) は不可能だと思います。代わりに、現在は反対の方向がより実現可能であると考えています。つまり、子エンティティの更新/作成を親エンティティから分離します。これは、次の方法で行うことができます。

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();
}
4

2 に答える 2

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();
}
于 2012-12-14T12:31:48.213 に答える
2

編集3:

モデル:

ここに画像の説明を入力

私は今、その質問を理解しています、と私は思います。エンティティを db コンテキストにアタッチし、その状態を正しく設定するにはどうすればよいですか。

問題は、ブログ インスタンスをアタッチすると、新規および既存の投稿のコレクションが含まれることです。解決策は、最初にブログ インスタンスの浅いコピーを (投稿のコレクションなしで) アタッチしてから、新しい投稿を追加することです。既存のインスタンスを changetracker にロードすることもできますが、これは db へのラウンドトリップを引き起こし、一部の SO 批評家をパーティーに引き付けます。

ところで、最初に正しいバージョンの 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);
            }

        }
于 2012-12-14T12:33:12.740 に答える