在WCF / .NET中返回DataTable

我有一个WCF服务,我想从中返回一个DataTable。 我知道这是一个非常激烈的话题,至于返回DataTable是否是一个好的做法。 我们暂且搁置一下。

当我从头开始创buildDataTable时,如下所示,不存在任何问题。 表被创build,填充并返回给客户端,一切都很好:

[DataContract] public DataTable GetTbl() { DataTable tbl = new DataTable("testTbl"); for(int i=0;i<100;i++) { tbl.Columns.Add(i); tbl.Rows.Add(new string[]{"testValue"}); } return tbl; } 

但是,一旦我出去打到数据库来创build表,如下所示,我得到一个CommunicationException“底层连接已closures:连接意外closures”。

 [DataContract] public DataTable GetTbl() { DataTable tbl = new DataTable("testTbl"); //Populate table with SQL query return tbl; } 

该表正在服务器端正确填充。 它比我循环并返回的testing表要小得多,查询又小又快 – 这里没有超时或大数据传输的问题。 正在使用相同的确切function和DataContracts / ServiceContracts / BehaviorContracts。

为什么填表的方式对表成功返回有什么影响?

对于有类似问题的人,我已经解决了我的问题。 这是几倍。

  • 正如Darren所build议的,Paul备份的,configuration中的Max..Size属性需要放大。 SvcTraceViewer实用程序帮助确定这一点,但它仍然不总是给出最有帮助的错误消息。
  • 当客户端更新服务引用时,configuration有时也不能正确更新(例如,更改服务器上的configuration值并不总是在客户端上正确更新,我必须进入并更改Max ..在我的debugging过程中,在客户端和服务器端多次调整属性大小)
  • 对于要被序列化的DataTable,需要给它一个名字。 默认的构造函数不给这个表一个名字,所以:

     return new DataTable(); 

    将不会被序列化,而:

     return new DataTable("someName"); 

    会将该表的名称作为parameter passing。

    请注意,通过为DataTable的TableName属性分配一个string,可以随时给一个表赋予一个名称。

     var table = new DataTable(); table.TableName = "someName"; 

希望这将有助于某人。

诊断这些types的WCF错误(真正不会告诉你很多)的最好方法是启用跟踪。 在您的web.config文件中,添加以下内容:

  <system.diagnostics> <sources> <source name="System.ServiceModel" switchValue="Information" propagateActivity="true"> <listeners> <add name="ServiceModelTraceListener" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="wcf-traces.svclog"/> </listeners> </source> </sources> </system.diagnostics> 

然后,您可以在.NET Framework SDK(或Visual Studio)中的SvcTraceViewer.exe实用程序中打开生成的文件。 在我的机器上,可以在%PROGRAMFILES%\ Microsoft SDKs \ Windows \ v6.0A \ Bin \ SvcTraceViewer.exe中find它。

只要找出一个错误信息(用粗体红色),就会明确告诉你你的问题是什么。

我添加了Datable到一个数据集,并像这样返回表…

 DataTable result = new DataTable("result"); //linq to populate the table Dataset ds = new DataSet(); ds.Tables.Add(result); return ds.Tables[0]; 

希望能帮助到你 :)

除了为所有绑定属性设置最大值之外。

确保你传递/从web服务返回的每个表必须有一个表名,这意味着table.tablename属性不应该是空的。

你想要的属性是OperationContract(在界面上)/ Operation Behavior(在方法上):

 [ServiceContract] public interface ITableProvider { [OperationContract] DataTable GetTbl(); } [OperationBehavior] public DataTable GetTbl(){ DataTable tbl = new DataTable("testTbl"); //Populate table with SQL query return tbl; } 

另外,在…我想服务configuration…你想指定的错误可以发送。 你可能会碰到一个类似于邮件大小的错误,等等。你可以通过与读者配额等进行混淆来解决这个问题。

默认情况下,wsHttpBinding的接收大小配额为65 KB,所以如果序列化的数据表的XML超过了这个数量,就会抛出一个错误(我95%确定数据表超过了65 KB )。

您可以在web.config / app.config更改阅读器配额等设置,也可以在代码中将其设置为绑定实例。 但是,是的,这可能是你的问题,如果你没有改变默认情况下。

WSHttpBindingBase成员 – 查看ReaderQuotas属性以及MaxReceivedMessageSize属性。

您可能会冒充配额 – 数据表大于连接允许的最大数据包大小。

您可能需要在连接上将MaxReceivedMessageSizeMaxBufferSize设置为更高的值。

我认为Darren很可能是正确的 – 为WCF提供的默认值是非常小的,如果碰到它们,最终会出现难以追查的错误。 当你试图做一个简单的testing用例以外的任何事情时,它们似乎就会出现。 我浪费了更多的时间,比我想要承认debugging问题的结果与客户端和服务器上的各种configuration(大小)设置有关。 我想我最终修改了几乎所有的,例如。 MaxBufferPoolSize,MaxBufferSize,MaxConnections,MaxReceivedMessageSize等

话虽如此,SvcTraceViewer实用程序也提到了很好。 我遇到了一些不如我喜欢的有用的情况,但总的来说,它是分析通信stream和错误的好工具。

在WCF服务中有3个返回types失败的原因是可数据的

  • 您必须指定数据表名称,如:

     MyTable=new DataTable("tableName"); 
  • 当你在WCF服务的客户端添加引用时,请select可重用的dll system.data

  • 指定datatable成员variables的属性

     [DataMember] public DataTable MyTable{ get; set; }