“无法在DateTime上调用方法”等限制

时间:2008-11-27 13:02:18

标签: .net sql linq linq-to-sql

有没有人知道在编译时没有被捕获的LINQ to SQL查询限制的确定列表,以及(如果可能的话)限制的变通方法?

我们到目前为止的清单是:

  • .Date上调用DateTime等方法
    • 找不到解决方法
  • string.IsNullOrEmpty
    • 简单,只需使用== ""代替
  • .Last()
    • 我们使用了.OrderByDescending(x => x.WhateverProperty).First()

5 个答案:

答案 0 :(得分:21)

基本上,这个列表很大......它是相对small set of things that are handled之外的所有内容。不幸的是,Law Of Leaky Abstractions开始了,每个提供商都有不同的答案......

LINQ-to-Objects将做任何事情(非常),因为它是委托; LINQ-to-SQL和Entity Framework具有不同的支持集。

一般来说,我使用DateTime属性等取得了相当大的成功 - 但实际上,您必须确保单元测试覆盖您的查询表达式,这样如果你曾经改变提供者(或提供者得到更新),你知道它仍然有效。

我想一个观点就是考虑TSQL;没有BOTTOM n,但有一个TOP 1(重新OrderByDescending);就string.IsNullOrEmpty而言,你可能非常直译:{{1​​}};使用foo.Bar == null || foo.Bar == "",您可以使用DateTime.Date /各种组件进行相当多的操作。

LINQ-to-SQL的另一个选择是将逻辑封装在UDF中 - 因此您可以编写一个带有DATEPART并返回datetime的UDF,并通过dbml将其公开数据上下文。然后,您可以在查询中使用它:

datetime

然而,这种方法并不一定能很好地利用索引。


更新

  • 支持的方法翻译等here
  • 支持的查询操作等为here

有关完整的血腥细节,您可以查看反射器中的where ctx.Date(foo.SomeDate) == DateTime.Today - 特别是System.Data.Linq.SqlClient.PostBindDotNetConverter+Visitor方法;一些Translate...函数是分开处理的。所以不是巨大的选择 - 但这是一个实现细节。

答案 1 :(得分:1)

LINQ是语言。 LINQ-to-SQL将您的LINQ命令编译为SQL查询。因此,它受到TSQL语法的正常限制,或者更容易被转换为它的项目的限制。

正如其他人所说,你不能做的事情的清单将是巨大的。这是一个小得多的列表,你可以做什么。一般的经验法则是尝试确定您要使用的函数将如何转换为TSQL。如果你很难搞清楚,那就不要使用那个功能(或者至少先测试一下)。

但是使用不在LINQ-to-SQL中的LINQ命令有一个简单的方法。将代码的纯LINQ部分与LINQ-to-SQL部分分开。换句话说,使用LINQ-to-SQL将数据拉入(使用LINQ-to_SQL中可用的任何函数),并将命令放入对象(ToEnumerable,ToList或其他类似的对象)中。这将执行查询并将数据拉到本地。现在它可用于完整的LINQ语法。

答案 2 :(得分:1)

我为String.IsNullOrEmpty()创建了一个Connect问题:

Feedback: I want to use string.IsNullOrEmpty in LINQ to SQL statements.

随意添加您的语音或投票,或为Linq to SQL中不起作用的各种其他方法创建其他Connect问题。吱吱作响的轮子得到油脂。

答案 3 :(得分:0)

我对DateTimes确实存在这个问题,并发现目前以下的解决方法适用于我,但我意识到,对于更大的结果集,它可能会成为一个问题因为处理现在在我的应用程序中而不是在数据库:

BlogPosts post = (from blogs in blogPosts
           where blogs.PostPath == path 
           select blogs)
           .ToList()
           .Where(blogs => blogs.Published.Date == publishedDate.Date)
           .SingleOrDefault();

请注意中间的“.ToList()” - 这会将其转换为正常的IEnumerable,并允许我使用我期望的常用属性。

然而,有一点让我感到困惑的是,这在EF中是合法的:

BlogPosts posts = from blogs in blogPosts
           where !blogs.IsDraft
             && blogs.Published.Year == year
             && blogs.Published.Month == month
           orderby blogs.Published descending
           select blogs

所以,我可以在DateTime上调用“.Year”或“.Month”,但不是“.Date” - 我想这可归结为类型。

答案 4 :(得分:0)

Marc Gravell的回答是完全正确的。

我只是想为Date Logic(和字符串比较)添加这个细节。由于您使用的是LinqToSql,因此您可以利用SqlMethods来完成您以前在数据库中所做的事情。