我为OData V4设置了一个WebApi端点。我没有直接使用实体框架,而是定义了一些POCO。
public class ServiceDTO
{
public string Id { get; set; }
public string Name { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
我的问题是在Odata控制器的Patch方法中我将检查If-Match标题如:
[AcceptVerbs("PATCH", "MERGE")]
public async Task<IHttpActionResult> Patch([FromODataUri] string key, Delta<ServiceDTO> patch, ODataQueryOptions<ServiceDTO> options)
{
if (patch == null)
{
var responseMessage = new HttpResponseMessage();
responseMessage.StatusCode = HttpStatusCode.ExpectationFailed;
responseMessage.Content = new StringContent("Missing properties");
return ResponseMessage(responseMessage);
}
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (options.IfMatch != null)
{
var result = this.repository.Get(options).AsQueryable().Where(u => u.Id == key);
if (!result.Any())
{
// The entity doesn't exist on the database and as the request contains an If-Match header we don't
// insert the entity instead (No UPSERT behavior if the If-Match header is present).
return NotFound();
}
else if (!((IQueryable<ServiceDTO>)options.IfMatch.ApplyTo(result)).Any())
{
// The ETag of the entity doesn't match the value sent on the If-Match header, so the entity has
// been modified by a third party between the entity retrieval and update..
return StatusCode(HttpStatusCode.PreconditionFailed);
}
else
{
// The entity exists in the database and the ETag of the entity matches the value on the If-Match
// header, so we update the entity.
var service = await this.repository.Get(key);
patch.Patch(service);
await this.repository.Update(service);
if (service == null)
return BadRequest();
return Ok(service);
}
}
else
{
var responseMessage = new HttpResponseMessage();
responseMessage.StatusCode = (HttpStatusCode)428;
return ResponseMessage(responseMessage);
}
}
在POCO中使用byte []我将始终以Precondition失败告终。当我将数据类型从byte []替换为string或int64时,一切正常。
我也尝试将DataAnnotation从[Timestamp]替换为[ConcurrencyCheck],但这没有效果。
我们之前在另一个带有byte的项目中使用过此代码,但我们直接使用EF。
存储库在运行时解析,它可以是与EF一起使用的存储库,也可以是与另一个后端一起使用的另一个自定义存储库。
我使用EF存储库和内存存储库进行了测试。