2010-11-03 74 views
0

我有一个应用程序使用WebServices向客户端发送数据库记录(作为数组),但即使只发送1000条记录,它似乎很慢。c#WebService压缩

服务器在IIS 7上运行,客户端是WPF应用程序。基本上,我如何加快速度。我是否必须编写自定义压缩类或代码?在IIS服务器和/或客户端配置文件中只有一个设置是打开/关闭的?现在需要大约4-7秒才能返回这1000条记录。因此,当我们将可能返回10,000到40,000条记录的表绑定在一起时,我不希望用户在那里等待数据等待几分钟。

下面的代码的一个例子:

Foo.svc:

namespace Foo.Server 
{ 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public sealed class FooService : IFoo 
    { 
     public SelectRecordsResponse SelectRecords(SelectRecordsRequest request) 
     { 
      //I tested to ensure that this isn't my bottleneck 
      FooBar[] records = ...; //Stores 1000 records 

      return new SelectRecordsResponse(records); 
     } 
    } 
} 

FooCommon.cs:

namespace Foo 
{ 
    [ServiceContract(Namespace = "http://www.company.com/Services/Foo", ConfigurationName = "IFoo")] 
    [ServiceKnownType(typeof(AbstractEntity))] 
    [XmlSerializerFormat(SupportFaults = true, Style = OperationFormatStyle.Document, Use = OperationFormatUse.Literal)] 
    public interface IFoo 
    { 
     [OperationContract(Action = "http://www.company.com/Services/Foo/SelectRecords", 
          ReplyAction = "http://www.company.com/Services/Foo/SelectRecordsReply", 
          Name = "SelectRecords")] 
     [ServiceKnownType(typeof(FooBar))] 
     [return: MessageParameter(Name = "Response")] 
     SelectRecordsResponse SelectRecords([MessageParameter(Name = "Request")]SelectRecordsRequest request); 
    } 

    [MessageContract(WrapperName = "SelectRecordsRequest", WrapperNamespace = "http://www.company.com/Services/Foo/", IsWrapped = true)] 
    public sealed class SelectRecordsRequest 
    { 
     public SelectRecordsRequest() 
     { 
     } 
    } 

    [MessageContract(WrapperName = "SelectRecordsResponse", WrapperNamespace = "http://www.company.com/Services/Foo/", IsWrapped = true)] 
    public sealed class SelectRecordsResponse 
    { 
     public SelectRecordsResponse() 
     { 
      Init(); 
     } 

     public SelectRecordsResponse(FooBar[] records = null) 
     { 
      Init(records); 
     } 

     private void Init(FooBar[] records = null) 
     { 
      Records = records ?? new FooBar[0]; 
     } 

     [MessageBodyMember(Namespace = "http://www.company.com/Services/Foo/", Order = 0, Name = "Records")] 
     [XmlArray(ElementName = "SelectRecordsArray", Form = XmlSchemaForm.Qualified)] 
     [XmlArrayItem(typeof(FooBar), ElementName = "SelectRecordsFooBar", Form = XmlSchemaForm.Qualified, IsNullable = true)] 
     private FooBar[] Records { get; set; } 
    } 
} 

FooClient.cs:

namespace Foo.Client 
{ 
    public interface IFooChannel : IFoo, IClientChannel 
    { 
    } 

    public sealed class FooClient : ClientBase<IFoo>, IFoo 
    { 
     public FooClient(String endpointConfigurationName) : 
      base(endpointConfigurationName) 
     { 
     } 

     public FooBar[] SelectRecords() 
     { 
      SelectRecordsRequest request = new SelectRecordsRequest(); 
      SelectRecordsResponse response = ((IFoo)(Client)).SelectRecords(request); 

      return response.Records; 
     } 

     SelectRecordsResponse IFoo.SelectRecords(SelectRecordsRequest request) 
     { 
      return Channel.SelectRecords(request); 
     } 
    } 
} 
+1

如果查询向客户端返回40000条记录,则查询很可能是错误的。在将结果返回给客户端之前,可能应该对结果进行汇总或过滤。 – 2010-11-03 15:15:32

+0

你应该实现“分页”。你永远无法*一举返回40,000条记录。 – 2010-11-03 15:41:32

+0

我确实正在过滤和分页,但有一些客户希望每个记录一次在数据网格中可见。无论哪种方式,100个记录或40,000我仍然需要实施某种压缩。 – 2010-11-03 15:50:19

回答

0

看来,最好的减少分配时间的方式是在评论中提出的一个建议,即对数据进行分页,以减少分发数量。我确实同意使用XML序列化以外的东西会加快速度,但还不够。此外,使用其他序列化是不可接受的,因为我们必须采用互操作序列化方法,以防出现Java客户端。

0

你有没有考虑过使用Microsoft Synchronization Services这对WCF有效?

我已经在过去使用它将数据同步到客户端,并将数据同步到具有相似记录数的服务器。它允许您根据特定标准过滤数据并允许增量下载。

但是,即使在使用同步服务时,在同步大量数据时,我的确注意到速度很慢。这是因为默认情况下数据被序列化为Xml,我使用binary encoder来解决这个问题。

2

很可能,您的性能瓶颈是SelectRecordsResponse对象的序列化和反序列化。我可以从最低到最高难度提供多种方式,使其更快,依次是:

  1. 使用NETTCP协议
  2. 使用二进制消息编码。
  3. 确保您使用DataContract串行而不是XML串行
  4. custom serializer - 这应该是您的最后手段,但可能让你做出最大的性能改进