C# 实体框架(EF)修改已在上下文中的实例
我正在做一个包含桌面(windows窗体)和windows phone应用程序的学校项目。错误在Api控制器的编辑操作中 这是WebApi调用:C# 实体框架(EF)修改已在上下文中的实例,c#,asp.net,asp.net-mvc,entity-framework,asp.net-web-api,C#,Asp.net,Asp.net Mvc,Entity Framework,Asp.net Web Api,我正在做一个包含桌面(windows窗体)和windows phone应用程序的学校项目。错误在Api控制器的编辑操作中 这是WebApi调用: HttpResponseMessage responseProizvodi; if (proizvod.ProizvodID == 0) responseProizvodi = proizvodiService.PostResponse(proizvod); else r
HttpResponseMessage responseProizvodi;
if (proizvod.ProizvodID == 0)
responseProizvodi = proizvodiService.PostResponse(proizvod);
else responseProizvodi = proizvodiService.PutResponse(proizvod.ProizvodID,proizvod);
WebApiHelper类中的我的方法:
public HttpResponseMessage PostResponse(Object o)
{
return client.PostAsJsonAsync(route, o).Result;
}
public HttpResponseMessage PutResponse(int id, Object o)
{
return client.PutAsJsonAsync(route + "/" + id, o).Result;
}
以及使用实体框架生成的ApiController:
[ResponseType(typeof(void))]
public IHttpActionResult PutProizvodi(int id, Proizvodi proizvodi)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != proizvodi.ProizvodID)
{
return BadRequest();
}
db.Entry(proizvodi).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ProizvodiExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
在这一行:
db.Entry(proizvodi).State = EntityState.Modified;
我得到了这个错误:
其他信息:附加“WebApi.Models.Proizvodi”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”
我阅读了关于类似主题的问题/答案,但没有找到答案
其中一个说我们必须分离本地版本并设置为修改我们正在修改的实体
一种方法是在DbSet的local中导航,以查看是否存在此数据库。如果实体存在,则拆离
var local = yourDbContext.Set<YourModel>()
.Local
.FirstOrDefault(f => f.Id == yourModel.Id);
if (local != null)
{
yourDbContext.Entry(local).State = EntityState.Detached;
}
yourDbContext.Entry(applicationModel).State = EntityState.Modified;
EF没有跟踪传递给您的
PutProizvodi
方法的Proizvodi
对象(即,它不知道它来自何处,因为它没有参与实体实例的创建;该实例是由Web.API模型绑定器创建的,它不知道您的数据库或EF)这可能就是它抛出错误的原因
仅仅因为类型Proizvodi
是一个实体类型,并不意味着EF会自动跟踪它;仅跟踪EF检索到的对象
首先,您需要使用传递给PutProizvodi
方法的id
通过EF查找右Proizvodi
对象的实例,而不是使用模型绑定器传递的Proizvodi
实例,从而获得右Proizvodi
对象的实例
您可以使用Proizvodi
对象传递到PutProizvodi
方法中,但更典型的做法是创建具有类似属性的模型,然后根据需要映射到实体实例。这允许您控制实体对象的哪些属性传入和传出应用程序
大概是这样的:-
[ResponseType(typeof(void))]
public IHttpActionResult PutProizvodi(int id, ProizvodiModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// lookup the entity using the id that was passed in
var proizvodi = db.Set<Proizvodi>().Where(x => x.id == id).FirstOrDefault();
// if no entity was found with that id, return
if (proizvodi == null) {
return BadRequest();
}
// make the changes to your entity
proizvodi.SomeProperty = model.SomeProperty;
// etc
// then save the changes
db.SaveChanges();
return StatusCode(HttpStatusCode.NoContent);
}
public class ProizvodiModel
{
public string SomeProperty { get; set; }
}
[ResponseType(typeof(void))]
公共IHttpActionResult PutProizvodi(int id,ProizvodiModel模型)
{
如果(!ModelState.IsValid)
{
返回请求(ModelState);
}
//使用传入的id查找实体
var proizvodi=db.Set(),其中(x=>x.id==id).FirstOrDefault();
//如果找不到具有该id的实体,则返回
if(proizvodi==null){
返回请求();
}
//对实体进行更改
proizvodi.SomeProperty=model.SomeProperty;
//等
//然后保存更改
db.SaveChanges();
返回状态码(HttpStatusCode.NoContent);
}
公共类ProizvodiModel
{
公共字符串SomeProperty{get;set;}
}
传递给PutProizvodi
方法的Proizvodi
对象未被EF跟踪(即,它不知道它来自何处,因为它没有参与实体实例的创建;该实例是由Web.API模型绑定器创建的,它不知道您的数据库或EF)这可能就是它抛出错误的原因
仅仅因为类型Proizvodi
是一个实体类型,并不意味着EF会自动跟踪它;仅跟踪EF检索到的对象
首先,您需要使用传递给PutProizvodi
方法的id
通过EF查找右Proizvodi
对象的实例,而不是使用模型绑定器传递的Proizvodi
实例,从而获得右Proizvodi
对象的实例
您可以使用Proizvodi
对象传递到PutProizvodi
方法中,但更典型的做法是创建具有类似属性的模型,然后根据需要映射到实体实例。这允许您控制实体对象的哪些属性传入和传出应用程序
大概是这样的:-
[ResponseType(typeof(void))]
public IHttpActionResult PutProizvodi(int id, ProizvodiModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// lookup the entity using the id that was passed in
var proizvodi = db.Set<Proizvodi>().Where(x => x.id == id).FirstOrDefault();
// if no entity was found with that id, return
if (proizvodi == null) {
return BadRequest();
}
// make the changes to your entity
proizvodi.SomeProperty = model.SomeProperty;
// etc
// then save the changes
db.SaveChanges();
return StatusCode(HttpStatusCode.NoContent);
}
public class ProizvodiModel
{
public string SomeProperty { get; set; }
}
[ResponseType(typeof(void))]
公共IHttpActionResult PutProizvodi(int id,ProizvodiModel模型)
{
如果(!ModelState.IsValid)
{
返回请求(ModelState);
}
//使用传入的id查找实体
var proizvodi=db.Set(),其中(x=>x.id==id).FirstOrDefault();
//如果找不到具有该id的实体,则返回
if(proizvodi==null){
返回请求();
}
//对实体进行更改
proizvodi.SomeProperty=model.SomeProperty;
//等
//然后保存更改
db.SaveChanges();
返回状态码(HttpStatusCode.NoContent);
}
公共类ProizvodiModel
{
公共字符串SomeProperty{get;set;}
}
我意识到了我的问题所在。简言之,我做了以下工作:
一,
1.1
二,
三,
现在一切都好了。我希望我意识到问题所在。如果有人能从技术上准确地解释发生了什么,我会很高兴的。我是一个初学者,正在努力弄清楚事情是如何运作的,谢谢。我意识到了我的问题所在。简言之,我做了以下工作: 一, 1.1 二, 三,
现在一切都好了。我希望我意识到问题所在。如果有人能从技术上准确地解释发生了什么,我会很高兴的。我是一个初学者,正在尝试弄清楚事情是如何运作的,谢谢。不清楚您在哪里初始化或处理
db
。然而,对于一个web应用程序来说
WebAPIHelper proizvodiService = new WebAPIHelper("http://localhost:62312/", "api/Proizvodi");
private Proizvodi proizvod { get; set; }
HttpResponseMessage responseProizvodi=proizvodiService.GetResponse(ProizvodID);
Proizvodi p = responseProizvodi.Content.ReadAsAsync<Proizvodi().Result;
proizvod = p;
// do some edit on "proizvod" and put to database
HttpResponseMessage responseProizvod = proizvodiService.PutResponse(proizvod.ProizvodID,proizvod);
proizvod = new Proizvodi();