我有一个 WCF 服务,我想从中返回一个数据表。我知道,就返回 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。

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

有帮助吗?

解决方案

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

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

    return new DataTable();
    

    将不可序列化,同时:

    return new DataTable("someName");
    

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

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

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

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

其他提示

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

只需查找错误消息(以粗体红色显示),它就会具体告诉您问题所在。

我将 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(在接口上)/操作行为(在方法上):

[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 属性。

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

你可能需要设置 最大接收消息大小最大缓冲区大小 为您的连接带来更高的价值。

返回类型失败的原因有 3 个: datatable 在 WCF 服务中

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

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

  • 指定属性 datatable 成员变量如

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top