【发布时间】:2009-06-11 06:04:08
【问题描述】:
我目前正在阅读 Albahari 的 C# 3.0 in a Nutshell 书,在 page 292 上它说关于 LINQ:
LINQ 遵循需求驱动的拉动 模式,而不是供应驱动 推模型。
以上说法是什么意思?
pull 模型和 push 模型有什么区别?
【问题讨论】:
我目前正在阅读 Albahari 的 C# 3.0 in a Nutshell 书,在 page 292 上它说关于 LINQ:
LINQ 遵循需求驱动的拉动 模式,而不是供应驱动 推模型。
以上说法是什么意思?
pull 模型和 push 模型有什么区别?
【问题讨论】:
我是客户,我需要一些东西,从服务器拉它。
我是服务器,我有东西,推送给客户端。
【讨论】:
这意味着您的 LINQ 查询将根据您的查询从数据源中提取数据,并且只会在执行时完成。与推送模型相反,服务器在其末端生成数据,然后将数据推送到客户端。推送模型类似于 Blackberry Enterprise Server,其中电子邮件被推送到 Blackberry 设备,而不是设备不断地查询它。这也意味着自您的 LINQ 查询以来的任何更改都不会反映在您的数据集中。
【讨论】:
要真正理解(并欣赏)您需要考虑语句和表达式之间的区别。如您所知,C# 和 VB 等命令式编程语言传统上使用按顺序执行的语句来完成某些目标。在这样的方案中,您检索数据,然后将其推送到其他一些语句中。相比之下,函数式编程倾向于使用只是值的表达式。在 LINQ 的情况下,您声明了一个查询表达式,该表达式在某些时候将评估为一个值,但直到需要它才会这样做。作为程序员,这让您可以更专注于您的程序做了什么,而不是它是如何做的。更广泛地说,惰性描述了一种通常由函数式编程语言采用的评估策略。例如,如果您有如下声明:
let x = 2 * y + 7
惰性编程语言在明确需要之前不会费心评估表达式,但同时您可以通过绑定 x 来引用它。同样,当您在 LINQ 中进行如下声明时:
var collection = from s in S where predicate(s)
您已经声明了一个表达式并将其绑定到 collection,但在您使用 collection 执行某些操作之前,您实际上并不需要它em>。因此,您可以在代码中的任何位置声明它,而不必担心它在不使用时会占用内存,因此您现在更多地考虑您要解决的问题,而不是详细说明计算机应该如何运行关于解决它。
因此,总而言之,在(急切的)命令式编程中,您获取数据,然后将其推送到某个将对其进行操作的函数上。在(懒惰的)函数式编程中,您声明一个表达式,并在需要时对其进行评估,对于数据库内容,这意味着需要查询表达式值的函数将 pull 在需要时使用。 Push/Pull 确实是一个糟糕的术语。
【讨论】:
在拉取模型中,处理由结果的消费者发起(结果通过处理管道“拉取”)。
在推送模型中,处理由数据的生产者发起(数据被“推送”到处理管道中)。
因此,在任何一种情况下,将要处理的数据都是正在执行的操作,并且它移动的“方向”(推/拉)是相对于触发处理的人而言的。
【讨论】: