在WCF / .NET中返回数据表

时间:2020-03-05 18:39:58  来源:igfitidea点击:

我有一个WCF服务,我想从中返回一个DataTable。我知道,就返回DataTables是否是一个好习惯而言,这通常是一个备受争议的话题。让我们搁置片刻。

如下所述,当我从头开始创建DataTable时,没有任何问题。该表已创建,填充并返回给客户端,一切正常:

[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;
}

但是,一旦我出去访问数据库以创建表,如下所示,我得到了CommunicationException"基础连接已关闭:该连接意外关闭。"

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

    return tbl;
}

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

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

解决方案

回答

我们想要的属性是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;
}

另外,在...我认为是服务配置...中,我们想指定可以发送错误。我们可能会遇到类似消息大小过大的错误等。我们可以通过混淆阅读器配额等来解决此问题。

缺省情况下,wsHttpBinding的接收大小配额为65KB,因此,如果序列化数据表的XML大于XML,它将抛出一个错误(我95%确信数据表中的数据大于65KB)。

我们可以在web.config/app.config中更改阅读器配额的设置,也可以在代码中的绑定实例上进行设置。但是,是的,如果我们没有默认更改它,那可能就是问题。

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

回答

诊断此类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中找到它。

只需查找一条错误消息(红色粗体),它将特别告诉我们问题所在。

回答

我认为Darren最有可能纠正了为WCF提供的默认值小得可笑的问题,如果碰到这些默认值,最终会遇到难以跟踪的错误。只要我们尝试执行除简单测试用例之外的任何操作,它们就会出现。我浪费了更多的时间,而不是想花很多时间来调试与客户端和服务器上的各种配置(大小)设置有关的调试问题。我想我最终修改了几乎所有它们,例如。 MaxBufferPoolSize,MaxBufferSize,MaxConnections,MaxReceivedMessageSize等。

话虽这么说,SvcTraceViewer实用工具也很棒。我确实遇到了一些情况,但并没有我想要的那样有用,但总的来说,它是分析通讯流和错误的好工具。

回答

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

  • 正如Darren的建议和Paul的备份一样,需要扩大配置中的Max..Size属性。 SvcTraceViewer实用程序有助于确定这一点,但它仍然不能始终提供最有用的错误消息。
  • 看来,当在客户端上更新服务参考时,有时配置可能无法正确更新(例如,在服务器上更改配置值并不能总是在客户端上正确更新。我必须进入并更改最大。在调试过程中,在客户端和服务器端都多次设置属性大小)
  • 为了使DataTable可序列化,需要为其指定一个名称。默认的构造函数不为表命名,因此:
return new DataTable();

将无法序列化,而:

return new DataTable("someName");

将为表命名,无论将其作为参数传递什么。请注意,可以通过为DataTable的TableName属性分配一个字符串来随时为表命名。

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

希望能对某人有所帮助。

回答

我们可能超出了配额,数据表大于了连接允许的最大数据包大小。

我们可能需要在连接上将MaxReceivedMessageSize和MaxBufferSize设置为更高的值。

回答

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

确保我们要从Web服务传递/返回的每个表都必须有一个表名,这意味着table.tablename属性不应为空。