where子句中的扩展方法

时间:2010-09-14 21:49:26

标签: c# linq .net-3.5

我在字符串类型上创建了一个简单的扩展方法:

public static bool Contains(this string word, string[] values)
{
    foreach(string s in values)
    {
        if(!word.Contains(s))
            return false;
    }

    return true;
}

现在,我有一个看起来像这样的linq查询:

public static IEnumerable<ISearchable> Search(params string[] keywords)
{
    XPQuery<Customer> customers = new XPQuery<Customer>(unitOfWork); // **
    var found = from c in customers
                where c.Notes.Contains(keywords)
                select c;

    return found.Cast<ISearchable>();
}

我在where子句中得到'method not supported'异常,如果我使用string.Contains方法,它将正常工作。

我的扩展方法有什么问题,或者我是否试图在linq where子句中使用它?

** XPQuery是一个devexpress组件,因为那是我正在使用的ORM,它是它们的linq-to-xpo查询对象。

4 个答案:

答案 0 :(得分:2)

您的代码是合法的C#,但您使用的框架可能不支持它。你可以试试这个:

where keywords.All(keyword => c.Notes.Contains(keyword))

我还建议您将方法重命名为ContainsAll,以区别于ContainsAny

答案 1 :(得分:2)

我的猜测是,linq-to-xpo不支持包含就像linq-to-entities v1.0(EF)不支持包含但linq-to-sql确实支持它。

这是实体框架的解决方法,也许你可以尝试一下。 'Contains()' workaround using Linq to Entities?

答案 2 :(得分:1)

LINQ-to-XPO尝试解析您的查询表达式并将其转换为SQL(或其他任何需要的东西),但它无法理解对自定义方法的调用。

通常,您需要重写查询以摆脱自定义方法(请参阅Mark的答案),或者您可以拆分查询以获取一些初步数据,然后使用LINQ-to-Objects选择所需的用你的方法设置。前者通常表现更好。

答案 3 :(得分:0)

我不知道XPQuery,但我认为它使用表达式树并将其翻译成其他语言(例如LINQ to SQL,它生成SQL)。问题是库不知道您的扩展方法。它不知道应该生成哪些相应的代码(在目标语言中)代替您的方法。

一般来说,LINQ to SQL等框架都不支持在查询中使用自定义方法 - 因为它们看不到方法的“内部”以查看如何翻译它,所以你必须直接编码您的逻辑使用支持的方法(标准LINQ运算符)。 Mark的解决方案展示了如何做到这一点。