我有一个PUT API端点,我想在更新和存储之前检查具有指定ID的记录是否已存在。
来自EntityFramework / SQLServer世界,我发现尝试更新不存在的记录只会创建一个提供错误ID而不是抛出异常的新文档,这很奇怪。
这是我的控制器端点和我的repo方法的代码:
public Models.Widget Put(Models.Widget entity)
{
using (_unitOfWork)
{
var originalWidget = _widgetRepository.Get(entity.Id);
if(null == originalWidget)
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("Widget with id of {0} could not be found.", entity.Id)));
_widgetRepository.Store(entity);
_unitOfWork.SaveChanges();
return entity;
}
}
回购方法:
public Widget Get(long id)
{
var widget = Session.Load<Widget>("widgets/"+id);
return widget;
}
public void Store(Widget model)
{
Session.Store(model);
}
假设我们在控制器中通过了空检查,我得到的错误如下:
Message: "An error has occurred."
ExceptionMessage: "Attempted to associate a different object with id 'Widgets/33'."
我知道为什么我收到错误,我最终&#34;追踪&#34; 2个具有相同身份的实体。
我有两种可能的解决方案,希望得到您的反馈。
你们觉得怎么样?
答案 0 :(得分:2)
Raven的Store方法类似于SQL Server中的INSERT。没有UPDATE,您只需从数据库中加载对象(将其置于更改跟踪中),更改它,然后调用SaveChanges。
告诉Raven&#34;这是我通过HTTP获取的这个对象不是一个好主意,请使用这些内容更新此文档ID&#34;因为那时你会放弃Raven的电子标签,让你控制并发。
根据您的情况,将您的Raven模型通过WebAPI直接发送到客户端,然后直接返回它们可能是也可能不是最佳选择。无论您是否使用完全相同的类或单独的DTO类型类与客户端进行通信,您都可以使用AutoMapper将来自通过WebAPI传入的对象的属性映射到从数据库加载的RavenDB模型。
答案 1 :(得分:1)
尝试使用optimistic concurrency。通过这种方式,您可以检测是否正在编写已使用ID的文档:
session.Advanced.UseOptimisticConcurrency = true;