大量数据的WCF服务最佳实践?

8
我们有一个用于查询基础数据存储(现在是 SQL Server 2005)的 WCF 服务。该服务可能返回相当大量的数据;我们实体类的实例数超过 60000,每个实例包含约 20 个属性。这些属性大多是原始类型,例如字符串、整数、日期时间等,其中有一些指向其他实体,而这些实体可能又指向其他实体,但层次结构不是很深。
使用该服务的一个应用程序通常会进行一些查询,只返回合理数量的实体(从几个实例到几千个实例)。但偶尔会进行一些查询,如上所述,返回大量数据(并且需要处理这些数据,因此缩小查询条件不是选项)。
我们想要做的是引入某种“分页”功能,客户端可以调用服务并获取一定数量的实例,然后再次调用并获取下一块数据,依此类推,直到获取完整结果。由于没有与 WCF 工作过多,我不太确定实现这一点的最佳方法。
也许需要记住的一件事是,在获取这些块的同时,基础数据可能会发生变化。我不太确定这对我们是否有问题(需要稍加调查),但它可能存在问题,因此,任何关于处理该特定情况的建议也是欢迎的。
我们已经开始研究流式响应,但也想看到分页示例,因为我们可能希望在接收完整结果之前开始处理数据。
简而言之,问题是:是否有最佳实践适用于这种情况(或者任何绝对的禁忌需要我们注意)?

1
Fredrik,你看过这个吗 - https://dev59.com/BnRB5IYBdhLWcg3wCjgV 尽管有点基础。 - RichardOD
@RichardOD:感谢提供链接。我认为我们需要从一个比那更低的层面来解决这个问题,但我会花些时间来进行试验。 - Fredrik Mörk
1个回答

9
在客户端和服务器上使用流绑定配置,使用仅具有流[MessageBodyMember](以及任何其他元数据作为[MessageHeader]发送)的MessageContract,可以让您在一个调用中完成整个过程,而不必担心分页(只需在服务器端使用枚举器来提供流并在客户端出现单个实体时处理它们),但是您必须在流内部自己进行框架协商(例如,使用DataContractSerializer手动对流进行序列化/反序列化实体)。我已经这样做了,它非常有效,但有点繁琐。
如果您想要进行分页,则简单的方法是与快照事务一起使用会话型WCF通道(如果您正在使用SQL Server或其他支持它们作为实体源的东西)。在第一个请求上启动快照tx,然后将tx的生命周期与会话绑定,以便在页面请求之间查看数据的稳定图像-当会话关闭(或在客户端意外断开连接时超时)时,tx将被释放。然后客户端请求它看到的最后一个键值+它想要的记录数(小心maxReceivedMessageSize-留下很多空间)。由于您处于快照状态,因此无需担心更改-您将在转储期间看到一致的视图。如果无法对源数据进行快照以防止在下载中更改,生活会变得更加困难。总是可以实现,但为此设计非常特定于数据。

感谢您的建议。我会研究快照事务的想法。目前看来,对于一些服务,我们可能需要转向 Linq-to-sql 来支持分页。我会检查这些想法是否可以结合起来,这将是理想的。 - Fredrik Mörk
他们可以 - 我们在所有情况下使用LINQ到SQL。快照的唯一技巧是,在开始时需要触碰所有记录(和相关数据)一次(但实际上不将其返回给客户端),以便将其包含在快照中。一个离散的SQL命令可能更好。 - nitzmahone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接