所以使用EF4,我正在运行一个搜索查询,以这个常见函数结束:
query = query.Skip(5).Take(10);
数据库中的这些记录有一个叫做印象派计数的列,我打算用它来计算每条记录在搜索结果页面上显示的次数。
最有效的方法是什么?首先,我要查看结果集,获取ID列表,然后使用ADO再次访问数据库。
UPDATE TableName SET ImpressionCount = ImpressionCount + 1 WHERE Id IN (1,2,3,4,5,6,7,8,9,10)
似乎足够简单,只是想知道是否有一个更。net 4/Linq-ish的方式来做到这一点,我没有想到。一个不涉及对数据库的另一次攻击的方法也会很好。:)
EDIT:所以我倾向于IAbstract的响应作为答案,因为它似乎没有"内置"的方式来做到这一点。我不认为有,但问问也无妨。然而,我想抛出的唯一另一个问题是:是否有可能编写一个只能对这个特定查询操作的SQL触发器?我不希望印象派计数更新每一个选择语句的记录(例如,当有人去查看详细页面,这不是一个印象-如果管理员编辑记录在后端,这不是一个印象)…是否可以使用LINQ ?
SQL Server将以某种方式需要能够识别查询是由Linq命令生成的,不确定这是否可能。这个网站的流量比较大,所以我只是尽量优化,但如果它是多余的,我可能只是继续并再次点击数据库的每一页的结果。
在我看来,最好继续运行SQL命令。仅仅因为我们有LINQ并不意味着它总是最好的选择。您的语句为您提供了一个调用过程来更新印象计数,并且应该相当快。
从技术上讲,您可以使用.Select
来修改返回结果中的每个元素,但这不是c#/linq的习惯用法,因此您最好使用foreach
循环。
的例子:
var query = query.ToList().Select(x => { x.ImpressionCount++; return x; });
正如IAbstract所说,要小心性能问题。使用上面的示例,或者一个foreach
将执行10次更新。你的一个更新语句更好。
我知道Linq2NHibernate也有同样的问题——试图坚持使用Linq对更新没有任何好处(这就是为什么它被称为"语言集成查询");
编辑:
实际上,EF4或NHibernate可能没有理由不能解析select表达式,意识到它是一个更新,并将其转换成一个更新语句并执行它,但肯定这两个框架都不会这样做。如果可能发生这种情况,您可能希望为IQueryable<T>
提供一个新的.Update()
扩展方法,以显式地声明您正在修改数据。使用.Select()
是一个肮脏的hack。
…这意味着没有理由不能为IQueryable<T>
编写自己的.Update(x => x.ImpressionCount++)
扩展方法,输出您想要的SQL并调用ExecuteStoreCommand,但这将是大量的工作。