编辑实体时的 EF 4.1 Code-First 和 ASP MVC 3 问题
我使用 DbContext 编码了我的实体并创建了 DbContext。然后我使用 MVC 脚手架为一个实体创建简单的 CRUD 表单。到目前为止一切顺利,它的效果正如广告中所宣传的那样。 现在,我决定用 DbContext 上的简单服务包装器替换脚手架生成的 DbContext。它所做的只是委托给 DbContext。
但是,现在在尝试编辑实体时,我在以下行中遇到了问题:
service.Entry(Book).State = EntityState.Modified;
“ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象”
我设法像这样解决它:
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
基本上,我再次获取实体并从视图传递给我的实体中复制属性。我还注意到,当我获得该实体时,它是代理,而交给我的实体则不是。
可能是什么问题?
这是我的服务类:
public class BookService
{
private DbContext context;
private DbSet<Book> set;
public BookService(DbContext context, DbSet<Book> set) {
this.context = context;
this.set = set;
}
public IQueryable<Book> Query
{
get { return set; }
}
public virtual void Add(Book entity)
{
set.Add(entity);
}
public virtual void Remove(Book entity)
{
set.Remove(entity);
}
public virtual void SaveChanges() {
context.SaveChanges();
}
public List<Book> All() {
List<Book> books = set.ToList();
return books;
}
public DbEntityEntry<Book> Entry(Book book) {
return context.Entry(book);
}
}
这是编辑操作控制器代码。我已经评论了原始的脚手架生成的代码:
[HttpPost]
public ActionResult Edit(Book book)
{
Book internalBook = service.Query.Single(b => b.Id == book.Id);
if (ModelState.IsValid)
{
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
service.Entry(internalBook).State = EntityState.Modified;
service.SaveChanges();
//context.Entry(book).State = EntityState.Modified;
//context.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
I coded my entities with and created DbContext. Then I used MVC Scaffolding to create simple CRUD form for one entity. So far so good, it works as advertised.
Now, I decided to replace scaffolding-generated DbContext with simple Service wrapper over DbContext. All it does is delegate to DbContext.
However, now I have the problem on the following line when tried to edit the entity:
service.Entry(Book).State = EntityState.Modified;
“An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key”
I managed to resolve it like this:
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
Basically, I get the entity again and copy properties from entity that was handed to me by View. I have also noted that when I obtain the entity, it is proxy, and the one handed to me is not.
What could be the problem?
Here is my service class:
public class BookService
{
private DbContext context;
private DbSet<Book> set;
public BookService(DbContext context, DbSet<Book> set) {
this.context = context;
this.set = set;
}
public IQueryable<Book> Query
{
get { return set; }
}
public virtual void Add(Book entity)
{
set.Add(entity);
}
public virtual void Remove(Book entity)
{
set.Remove(entity);
}
public virtual void SaveChanges() {
context.SaveChanges();
}
public List<Book> All() {
List<Book> books = set.ToList();
return books;
}
public DbEntityEntry<Book> Entry(Book book) {
return context.Entry(book);
}
}
Here is the Edit action Controller code. I have commented the original, scaffolding-generated code:
[HttpPost]
public ActionResult Edit(Book book)
{
Book internalBook = service.Query.Single(b => b.Id == book.Id);
if (ModelState.IsValid)
{
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
service.Entry(internalBook).State = EntityState.Modified;
service.SaveChanges();
//context.Entry(book).State = EntityState.Modified;
//context.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
实际上你不需要查询这本书,你可以只使用这两行:
所以这是完整的代码:
你可以从这篇文章下载完整的解决方案: http://blog.jorgef.net/2011/04/ef-poco-proxies-in-mvc.html
Actually you don't need to query the Book, you can just use these two lines:
So this is the complete code:
You can download a complete solution from this post: http://blog.jorgef.net/2011/04/ef-poco-proxies-in-mvc.html
您无法附加该书,因为您已将其加载到相同的上下文中。一般做法是这样的:
You can't attach the book because you have loaded it in the same context. General approach is this: