Linq:简单布尔函数返回linq异常

时间:2009-11-02 23:05:14

标签: linq-to-sql

我有一个看起来像这样的Linq查询:

var query = from x in table where SomeFunctionReturnsBool() select;

private bool SomeFunctionReturnsBool()
{
    return true;
}

这返回并说明“SomeFunctionReturnsBool没有支持的SQL转换”的异常。我知道这是因为它想将“SomeFunctionReturnsBool”视为一个表达式来评估为SQL,但它不能。

虽然这个Linq查询并不复杂,但真正的问题是。我怎样才能完成我在这里尝试做的事情,即打破查询的各个部分,希望能让它更具可读性?

杰夫

更新 好的答案。我现在正在尝试使用表达式,但是这段代码让我“无法解析方法Where(lambda表达式)”:

var query = from x in table where SomeFunctionReturnsBool() select x;

private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool
{
  return (x) => true;
}

5 个答案:

答案 0 :(得分:7)

另一种方法是使用Expression<Func<YourType, bool>>谓词...

var query = from x in table where SomeFunctionReturnsBool() select;

编辑:我通常不会按照上面显示的方式进行操作...我只是从上面的代码中获取它。这是我通常实现它的方式。因为那时你可以使用额外的Enumerable方法或在调试期间注释掉它们。

var results = table.Where(SomeFunctionReturnsBool())
    .OrderBy(yt => yt.YourProperty)
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
    //.Take(pageSize)
    .ToList(); //Finally executes the query...

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
    return (YourType yt) => yt.YourProperty.StartsWith("a")
        && yt.YourOtherProperty == true;
}

我更喜欢使用PredicateBuilder,它允许您构建一个在Where ...中使用的表达式

答案 1 :(得分:3)

您可以通过创建映射到数据上下文的UDF在LINQ-to-SQL中执行此操作;这涉及编写TSQL,并使用ctx.SomeFunctionblah(...)。

另一种方法是使用表达式树 - 例如,它可以是:

Expression<Func<Customer, bool>> SomeFunc() {
    return c => true; // or whatever
}

并使用.Where(SomeFunc()) - 足够接近?在这种情况下,您无法使用查询语法,但它可以完成工作......


添加了狡猾的Where方法,以显示您可能在查询语法中使用它的方式。我建议这很棒,但你可能会发现它很方便。

using System;
using System.Linq;
using System.Linq.Expressions;

static class Program
{
    static void Main()
    {
        using (var ctx = new NorthwindDataContext())
        {
            ctx.Log = Console.Out;
            // fluent API
            var qry = ctx.Customers.Where(SomeFunc("a"));
            Console.WriteLine(qry.Count());

            // custom Where - purely for illustration
            qry = from c in ctx.Customers
                  where SomeFunc("a")
                  select c;
            Console.WriteLine(qry.Count());
        }
    }
    static IQueryable<T> Where<T>(this IQueryable<T> query,
        Func<T, Expression<Func<T, bool>>> predicate)
    {
        if(predicate==null) throw new ArgumentNullException("predicate");
        return query.Where(predicate(default(T)));
    }
    static Expression<Func<Customer, bool>> SomeFunc(string arg)
    {
        return c => c.CompanyName.Contains(arg);
    }
}

答案 2 :(得分:2)

基本上,“开箱即用”,您不能让LINQ-to-SQL执行具有自定义函数的查询。实际上,只能使用一些可以转换为SQL的本机方法。

最简单的解决方法可能会影响性能,具体取决于您从数据库中恢复的数据量。

基本上,如果数据已经加载到内存中,那么只能在WHERE语句中使用自定义函数,即SQL已经执行。

您示例的最快修复方式如下:

var query = from x in table.ToList() where SomeFunctionReturnsBool() select;

注意ToList()。它执行SQL并将数据放入内存。您现在可以在WHERE语句/方法中执行任何操作。

答案 3 :(得分:1)

我会像这样打破它们:

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;

var query = from x in table where someTreeThatReturnsBool select x;

您可以创建传递表达式树的函数。

答案 4 :(得分:0)

不要使用查询语法。

var query = table.Where( x => SomeFunction(x) );