我们有一个WCF服务,用于查询底层数据存储(现在是SQL Server 2005)。该服务可能会返回相当大量的数据;我们的实体类的60000多个实例,包含~20个属性。这些属性大多是基元,例如string,int,DateTime,其中一对指向其他实体,而这些实体可能反过来指向其他实体;但这些等级制度并不是很深。
使用此服务的一个应用程序通常会生成仅返回合理数量的实体的查询(从几个实例到几千个)。但偶尔它会产生一个如上所述返回大量的查询(并且它将需要处理该数据,因此缩小查询条件不是一个选项)。
我们要做的是引入某种“分页”功能,客户端可以调用该服务并返回一定数量的实例,然后再次调用并获取下一个块,依此类推,直至满获取结果。没有与WCF合作太多,我不太确定实现这一目标的最佳方式。
可能要记住的一件事是,在获取块时,底层数据可能会发生很大变化。我不太确定这对我们来说是否是一个问题(需要稍微研究一下),但也可能是这样,所以处理这种特殊情况的任何输入也是受欢迎的。
我们已经开始研究流式传输响应,但是也希望看到分页样本,因为我们可能希望在收到完整结果之前开始处理数据。
所以,简而言之:这种情况是否存在最佳实践(或者我们应该注意的任何绝对禁忌)?
答案 0 :(得分:9)
在客户端和服务器上使用流绑定配置,MessageContract只有一个Stream [MessageBodyMember](以及作为[MessageHeader]发送的任何其他元数据),可以让你在一次调用中完成整个操作而不必担心分页(只是使用服务器端的枚举器来提供流并处理客户端上显示的各个实体),但是您必须在流中滚动自己的框架(例如,使用DataContractSerializer在流上手动序列化/反序列化实体或随你)。我已经做到了这一点,而且效果很好,但这有点痛苦。
如果要进行分页,最简单的方法是将会话WCF通道与快照事务结合使用(如果您使用的是SQL Server或其他支持它们作为实体源的内容)。在第一个请求上启动快照tx,然后将tx的生命周期与会话联系起来,这样您就可以在页面请求之间查看稳定的数据图片 - 会话结束时将释放tx(或者out,如果客户端意外断开连接)。然后客户端请求它看到的最后一个键值+它想要多少记录(小心maxReceivedMessageSize-留下很多空间)。由于您处于快照中,因此您无需担心更改 - 您将看到转储持续时间的一致视图。如果您无法对源数据进行快照以防止其在下载过程中发生变化,那么生活将变得更加艰难。始终可行,但为此设计非常特定于数据。