51

我有一个 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。

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

4

8 回答 8

83

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

  • 正如 Darren 建议和 Paul 支持的那样,需要扩大配置中的 Max..Size 属性。SvcTraceViewer 实用程序有助于确定这一点,但它并不总是提供最有用的错误消息。
  • 似乎在客户端更新服务参考时,配置有时不会正确更新(例如,更改服务器上的配置值不会总是在客户端正确更新。我不得不进去更改 Max..在我的调试过程中,在客户端和服务器端多次调整属性)
  • 要使 DataTable 可序列化,需要为其命名。默认构造函数没有给表命名,所以:

    return new DataTable();
    

    将不可序列化,而:

    return new DataTable("someName");
    

    将命名表作为参数传递的任何内容。

    请注意,可以随时通过将字符串分配给TableNameDataTable 的属性来为表命名。

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

希望这会对某人有所帮助。

于 2008-09-03T19:14:32.540 回答
15

诊断这些类型的 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 中找到它。

只需查找错误消息(以红色粗体显示),它将具体告诉您您的问题是什么。

于 2008-08-23T18:56:50.147 回答
5

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

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

于 2010-12-21T13:33:49.277 回答
5

我将Datable添加到数据集中并像这样返回表......

DataTable result = new DataTable("result");

//linq to populate the table

Dataset ds = new DataSet();
ds.Tables.Add(result);
return ds.Tables[0];

希望能帮助到你 :)

于 2011-10-24T08:29:51.093 回答
4

您想要的属性是 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 的接收大小配额为 65 KB,因此如果序列化数据表的 XML 超过此值,则会引发错误(我 95% 确定数据表超过 65 KB,其中包含数据)。

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

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

于 2008-08-15T20:35:00.977 回答
2

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

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

于 2008-10-24T13:33:35.373 回答
1

datatable与 WCF 服务一样,返回类型失败有 3 个原因

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

    MyTable=new DataTable("tableName");
    
  • 当您在 WCF 服务的客户端添加引用时,请选择可重用的 dllsystem.data

  • datatable在成员变量上指定属性,例如

    [DataMember]
    public DataTable MyTable{ get; set; }
    
于 2016-12-02T05:14:45.053 回答
0

我认为 Darren 很可能是正确的 - 为 WCF 提供的默认值小得可笑,如果碰到它们,最终会出现难以追踪的错误。当您尝试做任何超出简单测试用例的事情时,它们似乎就会出现。我浪费的时间比我想承认的调试问题要多,这些问题最终与客户端和服务器上的各种配置(大小)设置有关。我想我最终修改了几乎所有这些,例如。MaxBufferPoolSize、MaxBufferSize、MaxConnections、MaxReceivedMessageSize 等。

话虽如此,还提到的 SvcTraceViewer 实用程序很棒。我确实遇到了一些情况,它没有我希望的那么有用,但总的来说,它是分析通信流和错误的好工具。

于 2008-09-02T14:18:57.300 回答