我只是通过Visual Studio使用示例ASP.NET Mobile App Web API进行测试,并对并发检查提出了一些问题。
TableController<T>
要求使用以下内容提交更新:
protected virtual Task<TData> UpdateAsync(string id, Delta<TData> patch)
即。它需要Delta<T>
个更改。没有&#34;覆盖&#34;更新
项目中的样本实体是TodoItem
,它派生自EntityData
,它实现了一堆标准属性,其中一个是Version
属性,据我所知实体框架将检测作为并发属性以在更新之前检查版本。
我已经为Get
TodoItem
创建了一个测试客户端,更改了Text
属性,然后将其作为更新提交。
我发现如果我只是发送包含更新的Text
属性的Delta(当然还有URL中的Id
),那么我可以根据需要更新在此期间可能发生的覆盖和更改。
如果我更改了Delta,以便在我抓取时更新Text
属性和 Version
TodoItem
,那么如果我制作我的补丁请求如果在此期间发生了变化,我会收到409错误,正如预期的那样。
任何人都可以告诉我为什么这种Delta模式似乎允许你绕过并发检查,并且有没有办法确保检查总是发生?
答案 0 :(得分:0)
似乎 完全可以绕过并发检查,但它基于请求标头&#34; If-Match&#34;。
byte[] version = this.Request.GetVersionFromIfMatch();
if (version != null)
{
if (!patch.TrySetPropertyValue(TableUtils.VersionPropertyName, version))
{
string error = TResources.TableController_CouldNotSetVersion.FormatForUser(TableUtils.VersionPropertyName, version);
this.traceWriter.Error(error, this.Request, ServiceLogCategories.TableControllers);
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, error));
}
}
所以,如果没有&#34; If-Match&#34;版本然后不进行并发检查。
如果您使用的是Azure移动应用客户端SDK,那么&#34;版本&#34;你的实体的财产被提升了#34;然后加入&#34; If-Match&#34;标题为你。见https://docs.microsoft.com/en-gb/azure/app-service-mobile/app-service-mobile-dotnet-how-to-use-client-library#optimisticconcurrency
因此,如果要强制进行并发检查,则需要确保&#34; If-Match&#34;已设定。即
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
{
CheckUpdateForPrecondition();
return UpdateAsync(id, patch);
}
private void CheckUpdateForPrecondition()
{
if (!Request.Headers.Contains("If-Match"))
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("A pre-condition version must be supplied with Update (Header: If-Match).")
});
}