在WCF / .NET中返回DataTable

时间:2008-08-15 20:26:01

标签: c# .net wcf web-services datatable

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

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

8 个答案:

答案 0 :(得分:80)

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

  • 正如Darren建议并且Paul支持的那样,配置中的Max..Size属性需要扩大。 SvcTraceViewer实用程序帮助确定了这一点,但它仍然不总是提供最有用的错误消息。
  • 似乎在客户端更新服务引用时,配置有时也无法正确更新(例如,更改服务器上的配置值并不总是在客户端上正确更新。我必须进入并更改在我的调试过程中,客户端和服务器端的Max..Size属性多次)
  • 要使DataTable可序列化,需要为其指定名称。默认构造函数不为表提供名称,因此:

    return new DataTable();
    

    不可序列化,而:

    return new DataTable("someName");
    

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

    请注意,通过将字符串分配给DataTable的TableName属性,可以随时为表提供名称。

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

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

答案 1 :(得分:14)

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

只需查看错误消息(粗体红色),它会告诉您具体的问题。

答案 2 :(得分:5)

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

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

答案 3 :(得分:5)

我将Datable添加到数据集并返回表格,如此...

DataTable result = new DataTable("result");

//linq to populate the table

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

希望它有所帮助 :)

答案 4 :(得分:3)

您需要的属性是OperationContract(在界面上)/操作行为(在方法上):

[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 Members - 查看ReaderQuotas属性以及MaxReceivedMessageSize属性。

答案 5 :(得分:2)

您可能会破坏配额 - 数据表大于连接所允许的最大数据包大小。

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

答案 6 :(得分:1)

There are 3 reason for failed return type as datatable in WCF services

  • You have to specify data table name like:

    MyTable=new DataTable("tableName");
    
  • When you are adding reference on client side of WCF service select reusable dll system.data

  • Specify attribute on datatable member variable like

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

答案 7 :(得分:0)

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

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