这个问题也许是一个思想体系一个...
我有一个要求,从应用程序中调用通过服务代理的OData的网络API创建多个记录。
目前,我被(通过服务代理)调用POST方法多次,然后调用保存更改批量请求这样做。 例如。
container.AddToColours(new Colour { Id = 1, Name = "Green" });
container.AddToColours(new Colour { Id = 2, Name = "Orange" });
container.SaveChanges(SaveChangesOptions.Batch);
这种方法的缺点是,在我的Web API控制器POST方法被调用了两次,因此产生两个INSERT语句。
现在,如果我的客户这样做
container.AddToColours(new List<Colour>() { new Colour { Id = 1, Name = "Green" }, new Colour { Id = 2, Name = "Orange" }});
container.SaveChanges(SaveChangesOptions.Batch);
那么只有一个插入语句将创建一个同时插入两个记录。
该问题是;
这可能吗? (我可能最终有两个POST方法 - 一个为单一颜色相互接受的颜色列表)。
这是可能通过服务代理?
这是否触犯每/中的OData / REST本书的任何规则?
这是道德的?
这是调皮?
编辑
已经重新此,我已经能够如下建议创建一个自定义批量处理程序。 我希望这可以帮助别人。 它保存在一个批次中的一个事务中进行,所以如果该批次的一部分失败,那么所有部件失效的所有更改。 但是,重要的是,尝试以保存该批次的所有操作,无论先前的成功或失败,这样的错误信息可以为操作返回。
我在这里使用的样本为基础:
http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v3/ODataEFBatchSample/
但做了以下修改:
改变EntityFrameworkBatchHandler.ExecuteChangeSet方法:
private async Task ExecuteChangeSet(ChangeSetRequestItem changeSet, IList<ODataBatchResponseItem> responses, CancellationToken cancellation)
{
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }, TransactionScopeAsyncFlowOption.Enabled))
{
responses.Add((ChangeSetResponseItem) await new ChangeSetBatchRequestItem(changeSet).SendRequestAsync(Invoker, cancellation));
if (responses.All(x => (x as ChangeSetResponseItem).Responses.All(y => y.IsSuccessStatusCode)))
{
scope.Complete();
}
}
}
我认为,这意味着它不依赖于EF的。 我除去HttpRequestMessageExtensions.cs并创建了一个新的类,ChangeSetBatchRequestItem这是除了以下方法完全一样System.Web.OData.Batch.ChangeSetRequestItem:
public override async Task<ODataBatchResponseItem> SendRequestAsync(HttpMessageInvoker invoker, CancellationToken cancellationToken)
{
if (invoker == null)
{
throw new ArgumentNullException("invoker");
}
Dictionary<string, string> contentIdToLocationMapping = new Dictionary<string, string>();
List<HttpResponseMessage> responses = new List<HttpResponseMessage>();
try
{
foreach (HttpRequestMessage request in Requests)
{
responses.Add(await SendMessageAsync(invoker, request, cancellationToken, contentIdToLocationMapping));
}
}
catch
{
DisposeResponses(responses);
throw;
}
return new ChangeSetResponseItem(responses);
}
这就是很多。