【发布时间】:2014-08-24 23:54:53
【问题描述】:
我正在客户端使用 AngularJS 构建应用程序,后端使用 ASP.NET WebAPI/Entity Framework。
我需要确保完整的事务被存储或回滚,而不是依赖纯粹的 RESTful 服务。因此,我编写了一个 JavaScript UnitOfWork 实现,它跟踪我加载的每个对象,并按类型分别存储它们。
我在持久化它们时遇到了问题。
假设我通过 Web API 加载了以下对象:
{
FirstName: "Bob",
LastName: "Jensen",
Email: "test@example.com",
Country: { ID: 61, Name = "Zimbabwe"},
CountryID: 61,
Animals: [
{ Name: "Mittens", ID: 2},
{ Name: "Rex", ID: 1}
]
}
现在,假设我更改了 Bobs LastName 并想保存它。我将我的 UoW 发送到服务器,然后在 EF 上下文中,我对我编辑的对象执行以下操作(在此之前没有代码接触 obj):
databaseContext.Entry(obj).State = EntityState.Modified;
这给了我这样的错误:
附加类型为“MyApp.Model.Country”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
我的第一个想法是在将不需要的属性发送回服务器之前将其删除 - 所以在我上面的 JSON 中,我应该发回类似的结果,但没有“国家”和“动物”属性。我仍然想保留 CountryID。
- 如果不明确指定要删除的属性,这是否可行?
- 由于我面临这个问题,我的方法在概念上是否存在问题?我应该改为处理这个服务器端吗?
【问题讨论】:
-
我敢打赌你的上下文的生命周期太长了。
-
嗯.. 这实际上是一个我什至没有考虑过的有趣点。它存储在我的 ASP.NET 控制器上的一个私有字段中。我必须承认,我没有考虑过控制器被实例化的频率,只是假设它是每个请求一次。我认为我错了,明天会调查这个。谢谢!不过,我不希望为要发送的每个 UnitOfWork 序列化整个对象图。
-
@GertArnold:我检查过了,没有——我的控制器在每个请求上都会被实例化,所以我的内容只能用于一个查询/操作。
-
是的,这是 MVC 中的默认行为。但不知何故,这个实体在你显示的行之前被附加了。你能显示一些周围的代码吗?
-
你是如何获取 obj 的?我在某处看到有一些方法可以从数据库中获取它,这些方法已经将其标记为已修改,因此您只需要更新数据而不触及状态
标签: c# javascript json angularjs entity-framework