如何将大型数据集发送到WCF服务
本文关键字:WCF 服务 数据集 大型 | 更新日期: 2023-09-27 18:09:53
我想从WPF应用程序发送一个DataSet
到WCF服务。当我发送一个空的DataSet
它工作得很好。但是DataSet
和30 DataTable
给出了
远程服务器返回了一个意外的响应:(400)Bad Request.
我的操作合同是:
[OperationContract]
string InsertDataToDatabase(DataSet ds);
发送DataSet
到WCF服务的最佳方式是什么?
客户端App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICommunication" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="2147483647"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:49486/Communication.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICommunication"
contract="CommunicationReference.ICommunication" name="BasicHttpBinding_ICommunication" />
</client>
</system.serviceModel>
</configuration>
业务Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<connectionStrings>
<add name="ConName" connectionString="Data Source=WIN-7;Initial Catalog=ABC; User ID=sa; Password=****"/>
</connectionStrings>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!--To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment-->
<serviceMetadata httpGetEnabled="true"/>
<!--To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information-->
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="1000" maxConcurrentInstances="1600" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
我不记得曾经见过400错误消息的数据大小问题,但是…有几件事你可以试试。
这里发生了几件事。首先,根据你的服务配置文件,你是在。net 4.0上。这意味着你正在使用默认端点——你没有在配置中明确定义一个端点,所以框架会为你创建一个。并且它为适当的绑定使用默认值(在本例中为BasicHttpBinding
),这意味着即使您更改了所定义的绑定中的值,它们也不会生效。此外,您还将收到带有默认值的默认行为。
尝试在绑定中为maxReceivedMessageSize
和maxStringContentLength
设置一个更高的值(默认值是65536)。如果你增加maxStringContentLength
的大小,你也需要增加maxBufferSize
的大小到相同的值(至少)。
现在,由于您没有显式定义端点,因此您需要创建一个端点并将您定义的绑定分配给它,或者将您的定义作为默认值。
首先,绑定的更新版本(用于处理更大的数据)可能看起来像这样(只显示了需要更改的相关部分——为了简洁起见,我省略了其余部分)。我选择了一个相当大的数字-对于maxBufferSize
和maxReceivedMessageSize
,最大值是Int64的最大值,对于maxStringContentLength
,最大值是Int32的最大值。
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICommunication"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
接下来,您需要将此绑定分配给您的服务端点。最简单的方法,特别是在只有一个端点的情况下,是将绑定定义置于默认值之上。只需省略binding
元素中的name
属性即可。例如:
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
注意在上面的(剥离的)配置中没有name
属性。
第二种方法是创建一个端点,并将您定义的绑定配置分配给它。例如:
<services>
<service name="MyServiceName">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICommunication"
contract="MyService.IMyContract" />
</service>
</services>
我也看到有人在服务行为中增加了dataContractSerializer
元素的maxItemsInObjectGraph
属性,尽管我从来没有这样做过。根据MSDN文档,我认为这不适用于您的情况,因为您没有使用任何数据合同。然而,为了给你尽可能多的选项来解决这个问题,你可以通过在你的行为组中定义一个端点行为来进行调整,像这样:
<behaviors>
<endpointBehaviors>
<behavior name="LargeDataBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
同样,因为你是在。net 4.0上,你要么需要将此行为定义为默认行为(通过省略name
属性),要么将其分配给已定义的端点,就像这样(使用上面的端点示例):
<endpoint address=""
behaviorConfiguration="LargeDataBehavior"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICommunication"
contract="MyService.IMyContract" />
你也可以看看WCF流。