標籤:
我們在使用Entity Framework架構進行CRUD時,經常會出現各種各樣的錯誤,下面請看我的實驗結果。
以下是只用一個內容物件進行操作:
第一次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.Single(t => t.Id == 2); post.AuthorId = 1; blog.SaveChanges();
結果:成功
第二次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.Single(t => t.Id == 2); post.Author = blog.Authors.Single(t => t.Id == 3); blog.SaveChanges();
結果:成功
第三次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.Single(t => t.Id == 2); post.AuthorId = 1; post.Author = blog.Authors.Single(t => t.Id == 4); blog.SaveChanges();
結果:失敗,報錯如下:
Conflicting changes to the role ‘Post_Author_Target‘ of the relationship ‘ConsoleApplication1.DDD.Infrastructure.Post_Author‘ have been detected.
第四次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.Single(t => t.Id == 2); post.Author = new Author() { Id = 4 }; blog.Entry(post.Author).State = EntityState.Unchanged; blog.SaveChanges();
結果:成功
第五次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.Single(t => t.Id == 2); //author = new Author() { Id = 1, Name = "zwj" };//直接執行個體化或下面查詢得出 author = blog.Authors.AsNoTracking().Single(t => t.Id == 3); post.Author = author; blog.SaveChanges();
結果:成功,但是Authors表中會新增一筆記錄,並將新的ID賦值給Posts表;原因:Author與Post不在同一個上下文中,Post所在的上下文中追蹤不到Author的資訊,故當成新增。
以下是在兩個不同的上下文中進行操作:
第六次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); //blog.Entry(post).State = EntityState.Detached;上面的AsNoTracking可以由這句實現 BlogDbContext blog2 = new BlogDbContext(); post.AuthorId = 5; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:成功
第七次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); post.Author = blog2.Authors.Single(t => t.Id == 5); blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:失敗,報錯如下:
A referential integrity constraint violation occurred: The property value(s) of ‘Author.Id‘ on one end of a relationship do not match the property value(s) of ‘Post.AuthorId‘ on the other end.
第八次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); author = blog2.Authors.AsNoTracking().Single(t => t.Id == 1); post.Author = author; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:失敗,報錯同第七次
第九次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); author = blog.Authors.AsNoTracking().Single(t => t.Id == 3); BlogDbContext blog2 = new BlogDbContext(); post.Author = author; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:失敗,報錯同第七次
第十次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); author = new Author() { Id = 1, Name = "zwj" }; post.Author = author; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:失敗,報錯同第七次
第十一次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); author = blog2.Authors.Single(t => t.Id == 1); post.Author = author; post.AuthorId = author.Id; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:成功,但我認為主要是通過賦值AuthorId來完成的,與第六次相同,去掉賦值AuthorId,則與第七次相同的報錯
第十二次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); author = blog2.Authors.Single(t => t.Id == 3); blog2.Entry(post).Reference(t => t.Author).CurrentValue = author; blog2.Entry(post).State = EntityState.Modified; blog2.SaveChanges();
結果:失敗,報錯同第七次
第十三次:
BlogDbContext blog = new BlogDbContext(); post = blog.Posts.AsNoTracking().Single(t => t.Id == 2); BlogDbContext blog2 = new BlogDbContext(); blog2.Posts.Attach(post); post.Author = blog2.Authors.Single(t => t.Id == 1); blog2.SaveChanges();
結果:成功
最後得出結論:
1.在同一個上下文中,不論是採用直接賦值導覽屬性或是直接賦值外鍵屬性,除不能同時對導覽屬性及外鍵屬性賦不相關聯的值外,都可以成功;
2.不在同一個上下文中,若想在完成CUD時,則必需先確保要進行操作的實體處於Detached狀態,然後再進行相應的更新,涉及導覽屬性時,只能採用賦值外鍵屬性,不能通過導覽屬性直接賦值,否則會報錯(這個我覺得是個BUG,不知大家有什麼好的解決辦法沒有),若採用先在新的上下文中Attached,再進行更新操作則與第1條結論相同。
分享關於Entity Framework 進行CRUD操作實驗的結果