Web API和RavenDB - 在插入实体之前检查实体是否已存在

时间:2014-04-17 00:51:49

标签: c# .net asp.net-mvc ravendb nosql

我有一个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个具有相同身份的实体。

我有两种可能的解决方案,希望得到您的反馈。

  1. 找到一种有效的方法来检查是否存在没有加载原件进行跟踪的ID。
  2. 获取原始和&#34;补丁&#34;它们与传入的PUT DTO一起并将其存储在数据库中。
  3. 你们觉得怎么样?

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;