2017-05-19 19 views
0

이 내 OdataController낙관적 동시성 처리 Asp.Net WebApi 중 하나로, OData V4

public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> patch) 
{ 
    Validate(patch.GetInstance()); 
    Product product = await service.Products.GetAsync(key); 
    if (product == null) 
     return NotFound(); 

    patch.Put(product); 

    try 
    { 
     await service.Products.UpdateAsync(product); 
    } 
    catch (DbUpdateConcurrencyException) 
    { 
     if (!await service.Products.ExistAsync(key)) 
      return NotFound(); 
     else 
      throw; 
    } 

    return Updated(product); 
} 

내 모델의 Patch 방법 인 속성이 있습니다. Etag를 사용하여 동시성 검사 메커니즘을 구현해야합니다. 나는 here 몇 가지 예제를 보았습니다. 그러나 그들은 델타 메소드를 사용하지 않습니다.

  1. etags를 사용하여 동시성을 어떻게 확인할 수 있습니까?
  2. 동시성 해킹에 대한 사용자 지정 특성을 구현할 수 있습니까? 마찬가지로

뭔가 :

[CustomConcurrencyCheck] 
public async Task<IHttpActionResult> Put([FromODataUri] int key, Delta<Product> patch) 
{ 
... 
} 

간단한 예제를 제공은 높게 평가 될 것입니다. WebApiConfig 최초

+0

델타를 사용하는 경우 변경된 속성 만 가져옵니다. ETag 또는 RowVersion은 속성 이었지만이를 변경 했습니까? 당연히 아니지. 둘 다 델타 데이터에 없습니다. ETag 또는 RowVersion의 이전 값을 가지고 있지 않다면 어떻게 비교할 것입니까? –

+0

동일한 키에 대해 두 번 이상의 Put 작업이 동시에 처리되는 경우 현재 지점에서 DbUpdateConcurrencyException 만 표시됩니다. –

답변

1

모델을 만드는 동안 지정해야하는 특성 인의 ETag, 귀하의 경우 :

var builder = new ODataConventionModelBuilder(); 
builder.EntityType<Product>() 
    .Property(p => p.RowVersion) 
    .IsConcurrencyToken(); 

나중에 당신이 컨트롤러에 Patch 방법의 ODataQueryOptions<T> 매개 변수에서의 ETag를 검색 할 수 있습니다 :

[AcceptVerbs("PATCH", "MERGE")] 
public IHttpActionResult Patch([FromODataUri] int key, Delta<Product> delta, ODataQueryOptions<Product> options) { 
    var existingEntity = //Code to get existing entity by ID, 404 if not found 

    byte[] requestETag = options.IfMatch["RowVersion"] as byte[]; 
    if(!requestETag.SequanceEqual(existingEntity.RowVersion)) { //Simplified if-statement, also do null-checks and such 
     // ETags don't match, return HTTP 412 
     return StatusCode(HttpStatusCode.PreconditionFailed); 
    } else { 
     // The ETags match, implement code here to update your entity 
     // You can use the 'Delta<Product> delta' parameter to get the changes and use the 'Validate' function here 
     // ... 

은 업데이트를 요청하는 클라이언트가 서비스가있는 객체의 동일한 버전이 있는지 확인하는 간단한 검사입니다, 내가 사용하는 솔루션입니다. 내 솔루션의 주목할만한 단점은 DB에서 기존 개체를 검색하여 작동 시키면 성능이 저하된다는 것입니다.

이것은 If-Match 헤더의 코드이며, ODataQueryOptions<T>.IfNoneMatch[VersionColumnName]입니다. Get 방법에서 사용할 수 있습니다. If-None-Match 헤더가 RowVersion과 같은 경우 HTTP 304 (Not modified)을 반환하고 대역폭을 절약 할 수 있습니다.

최대 사용자의 맞춤 속성을 구현하려는 경우 매우 간단한 예입니다. 적어도이 논리의 일부를 도우미 클래스로 옮겨 재사용 할 수 있습니다.