Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rest 多个POST方法OData Web API。这应该/可能发生吗?_Rest_Odata_Asp.net Web Api_Asp.net Web Api2 - Fatal编程技术网

Rest 多个POST方法OData Web API。这应该/可能发生吗?

Rest 多个POST方法OData Web API。这应该/可能发生吗?,rest,odata,asp.net-web-api,asp.net-web-api2,Rest,Odata,Asp.net Web Api,Asp.net Web Api2,这个问题也许是一个理想的问题 我需要从通过服务代理调用ODataWebAPI的应用程序中创建多个记录 目前,我正在通过多次调用post方法(通过服务代理),然后调用save changes来批处理请求。例如 container.AddToColours(new Colour { Id = 1, Name = "Green" }); container.AddToColours(new Colour { Id = 2, Name = "Orange" }); contain

这个问题也许是一个理想的问题

我需要从通过服务代理调用ODataWebAPI的应用程序中创建多个记录

目前,我正在通过多次调用post方法(通过服务代理),然后调用save changes来批处理请求。例如

    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);
container.addToColor(新列表(){new color{Id=1,Name=“Green”},新颜色{Id=2,Name=“Orange”});
container.SaveChanges(SaveChangesOptions.Batch);
然后只创建一条insert语句,同时插入两条记录

问题是,

这可能吗?(我可能会有两种POST方法——一种是单一颜色,另一种是接受颜色列表)

这是否可以通过服务代理实现

这是否违反了OData/REST手册中的所有/任何规则

这是否合乎道德

这是淘气吗

编辑

重温这一点后,我能够创建一个定制的批处理程序,如下所示。我希望这能帮助其他人。它将在单个事务中保存批次中所做的所有更改,因此,如果批次的一部分失败,则所有部分都会失败。但是,重要的是,不管以前的成功或失败,都会尝试为批处理中的所有操作保存,因此可以返回错误消息进行操作

我使用这里的样本作为基础:

但作出了以下改变:

已将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();
            }
        }
    }
private async Task ExecuteChangeSet(ChangeSetRequestItem变更集、IList响应、CancellationToken取消)
{
使用(var scope=new TransactionScope(TransactionScopeOption.Required,new TransactionOptions(){IsolationLevel=IsolationLevel.ReadUncommitted},TransactionScopeAsyncFlowOption.Enabled))
{
Add((ChangeSetResponseItem)等待新的ChangeSetBatchRequestItem(changeSet).SendRequestAsync(调用者,取消));
if(responses.All(x=>(x为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);
    }
public override async Task SendRequestAsync(HttpMessageInvoker调用程序,CancellationToken CancellationToken)
{
if(调用程序==null)
{
抛出新的ArgumentNullException(“调用程序”);
}
Dictionary contentIdToLocationMapping=新字典();
列表响应=新列表();
尝试
{
foreach(请求中的HttpRequestMessage请求)
{
Add(等待SendMessageAsync(调用程序、请求、取消令牌、contentIdToLocationMapping));
}
}
抓住
{
处置响应(响应);
投掷;
}
返回新的ChangeSetResponseItem(响应);
}

谢谢你的回答,这里是我对你问题的回答

  • 在请求主体中发布多个实体(如果不是批处理请求)不是传统的OData请求
  • 控制器中的Post方法被调用两次并不意味着客户端发送两个Post请求。实际上,客户机发出一个批处理请求,其中包含2个POST作为其子请求。批处理程序将每个子请求分派给WebAPI管道,然后WebAPI将所有子响应组合成一个,并将其发送回请求者。详情请参阅

  • 允许并记录在批次处理下的OData规范中。我看不出为什么会是“不道德的”或“顽皮的”。在“这可能吗”中“这”是什么意思?@TanJinfu-这可能吗:我的建议意味着我的OData Web API控制器中将有两个POST方法。一个接受颜色类型的对象,另一个接受颜色类型的集合。当我调用container.addtocolors时,我在我的应用程序中发现了一个问题,它如何知道使用什么post方法?@SimonBelanger;如果有文档记录,是否有通过服务代理实现的方法?当container.SaveChanges(SaveChangesOptions.Batch)时,对container.addToColor的每次调用都会导致对Web API控制器的POST方法的单独调用;被称为。我将如何使它调用后的方法,一旦发送每一个新的颜色?谢谢你的答复。我来看看。您知道有没有一种方法可以在批处理时不导致数据库被命中两次?我想这涉及到使用自定义批处理而不是标准路由。我不确定,但我认为这涉及到使用自定义批处理程序而不是路由。