2009-08-17 39 views
1

我在IIS中使用basicHttpBinding使用流模式托管WCF服务。 WCF Web服务通过使用ADO.Net查询后端SQL Server 2008,并将DataTable返回给WCF服务的客户端。WCF流模式问题

我的WCF流模式是理解,

  1. WCF流模式应该使用在客户端和服务器端的唯一不变的数量的内存;
  2. WCF流模式应该能够在客户端和服务器之间传输任意数量的数据。

我的理解是否正确?

如果是的话,我下面的示例打破这两个规则,我观察到两种违法行为,

  1. 我发现我下面的示例继续吃内存(从任务管理器,内存使用量增加的性能选项卡)。我在同一台机器上运行客户端和服务器。那么,WCF流媒体模式不会使用恒定数量的内存?

  2. 当传输10M行的一个DataTable时,下面有异常发布。但传输1M行很好。那么,WCF流媒体模式不能传输任何数量的数据?

任何想法是什么错?

异常消息:在接收到 http://labmachine1/service.svc的 HTTP响应

发生错误。这个 可能是由于服务端点 绑定不使用HTTP协议。 这也可能是由于HTTP 请求上下文被 服务器中止(可能归因于服务 关闭)。有关更多详细信息,请参阅服务器日志 。

{“基础连接已经关闭:发生意外的错误 接收。”}

这里是我的服务器端的整个源代码,在web.config中的服务器I宿主,换不换默认值。由于我在IIS中托管,我正在使用basicHttpBinding。

public class StudentManagement : IStudentManagement 
{ 
    public DataTable Poll(int Id) 
    { 
     return MakeParentTable(); 
    } 

    private DataTable MakeParentTable() 
    { 
     // Create a new DataTable. 
     System.Data.DataTable table = new DataTable("ParentTable"); 
     // Declare variables for DataColumn and DataRow objects. 
     DataColumn column; 
     DataRow row; 

     // Create new DataColumn, set DataType, 
     // ColumnName and add to DataTable.  
     column = new DataColumn(); 
     column.DataType = System.Type.GetType("System.Int32"); 
     column.ColumnName = "id"; 
     column.ReadOnly = true; 
     column.Unique = true; 
     // Add the Column to the DataColumnCollection. 
     table.Columns.Add(column); 

     // Create second column. 
     column = new DataColumn(); 
     column.DataType = System.Type.GetType("System.String"); 
     column.ColumnName = "ParentItem"; 
     column.AutoIncrement = false; 
     column.Caption = "ParentItem"; 
     column.ReadOnly = false; 
     column.Unique = false; 
     // Add the column to the table. 
     table.Columns.Add(column); 

     // Make the ID column the primary key column. 
     DataColumn[] PrimaryKeyColumns = new DataColumn[1]; 
     PrimaryKeyColumns[0] = table.Columns["id"]; 
     table.PrimaryKey = PrimaryKeyColumns; 

     // Create three new DataRow objects and add 
     // them to the DataTable 
     for (int i = 0; i <= 10000000; i++) 
     { 
      row = table.NewRow(); 
      row["id"] = i; 
      row["ParentItem"] = "ParentItem " + i; 
      table.Rows.Add(row); 
     } 

     return table; 
    } 
} 

客户端代码:

static void Main(string[] args) 
{ 
    StudentIdentifier identifier = new StudentIdentifier(); 
    identifier.Id = 100; 
    StudentManagementClient client = new StudentManagementClient(); 

    DataTable student = client.Poll(identifier); 

    Console.WriteLine(student.Rows.Count); 
} 

对客户端的app.config流模式配置,

<basicHttpBinding> 
     <binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00" 
     openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" 
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
     maxBufferSize="1500000000" maxBufferPoolSize="1500000000" maxReceivedMessageSize="1500000000" 
     messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed" 
     useDefaultWebProxy="true"> 
     <readerQuotas maxDepth="1500000000" maxStringContentLength="1500000000" 
      maxArrayLength="1500000000" maxBytesPerRead="1500000000" maxNameTableCharCount="1500000000" /> 
     <security mode="None"> 
      <transport clientCredentialType="None" proxyCredentialType="None" 
      realm="" /> 
      <message clientCredentialType="UserName" algorithmSuite="Default" /> 
     </security> 
     </binding> 
    </basicHttpBinding> 

服务器端的web.config的流模式,

<basicHttpBinding> 
    <binding name="BasicHttpBinding_IStudentManagement" closeTimeout="00:01:00" 
     openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" 
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
     maxBufferSize="1000000000" maxBufferPoolSize="1000000000" maxReceivedMessageSize="1000000000" 
     messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed" 
     useDefaultWebProxy="true"> 
     <readerQuotas maxDepth="32" maxStringContentLength="1000000000" maxArrayLength="1000000000" 
      maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
     <security mode="None"> 
     <transport clientCredentialType="None" proxyCredentialType="None" 
      realm="" /> 
     <message clientCredentialType="UserName" algorithmSuite="Default" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 

回答

0

maxB ufferSize属性约束了WCF在发送/接收流式数据时使用的内存量。但是,在将大对象发送到客户端之前,您正在将大对象加载到内存中。

我会首先建议您使用DTO(数据传输对象)将数据发送给客户端,并且如果您需要将大量数据发送到客户端,那么您将实现分页机制以便以可管理的块传输数据。

从理论上讲,您可以使用WCF向客户端发送1000万条记录,实际上,客户端几乎不需要一次性处理那么多的数据。

1

在流模式下,您必须使用system.io.stream作为返回类型或参数类型。显然,你没有这样做。