【发布时间】:2016-04-01 22:31:35
【问题描述】:
我正在处理包含桌面(Windows 窗体)和 Windows Phone 应用程序的学校项目。错误在 Api 控制器,编辑操作中。
这是 WebApi 调用:
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;
}
和使用Entity Framework生成的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”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
我阅读了类似主题的问题/答案,但没有找到答案。
其中一个说我们必须分离本地版本并设置修改我们正在修改的实体。
一种方法是在 DbSet 的本地内部导航以查看是否存在该 DbSet。如果实体存在,则分离。
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;
在我的例子中,local 是 null,EntityState 是 Deatached,但我仍然有同样的错误。有什么帮助吗?
编辑: 我的数据库在这里:
public class ProizvodiController : ApiController
{
private eProdajaEntities db = new eProdajaEntities();
//actions
}
【问题讨论】:
-
不清楚您在哪里初始化或处置
db。但是,对于 Web 应用程序,在多个 HTTP 调用中保持打开 DbContext 是一种不好的做法。当多个客户端访问上下文时,它将处于混乱和混乱的状态。最佳做法是在您的操作方法的主体中创建和处置您的 DbContext。 -
Db 被实例化为 Controller 类的私有成员: public class ProizvodiController : ApiController { private eProdajaEntities db = new eProdajaEntities(); //动作 //动作 //.... }
-
接受整个域对象然后保存它是一个明显的安全漏洞。您应该细化您希望编辑的属性,然后自己更新域对象。使用这种方法,您一开始就不会遇到此错误。
-
可能你的 Dbcontext 没有正确处理。
-
您必须先从上下文中获取实体,然后才能附加它以进行更改。 EF 无法知道您的 proizvodi 是上下文的一部分。我看到的情况是,由于 Ef 不知道您的 proizvodi,它会创建一个新的,这会导致“相同的主键值”错误。
标签: c# asp.net asp.net-mvc entity-framework asp.net-web-api