LINQ to Nhibernate用户定义的where子句中的函数

时间:2012-12-03 08:26:59

标签: c# linq nhibernate

我正在尝试执行以下操作:

var query =
    (from a in session.Query<A>()
    where a.BasicSearch(searchString) == true
    select a);

但它一直给我这个例外“System.NotSupportedException”!

知道如何解决这个问题吗?

4 个答案:

答案 0 :(得分:7)

在LINQ查询中无法使用用户定义的函数。 NHibernate linq提供程序不知道如何将函数转换为SQL。

LINQ to NHibernate通过检查您在运行时提供的LINQ表达式,并将它在此表达式树中找到的内容转换为常规SQL表达式来工作。这是一篇很好的文章,可以了解表达式树的一些背景知识:http://blogs.msdn.com/b/charlie/archive/2008/01/31/expression-tree-basics.aspx

然而,您可以使用techniques discussed here以另一种方式重用这样的谓词。 (我不确定这是否适用于NHibernate。)如果它有效,它看起来像这样:

// this could be a static method on class A
public static Expression<Func<A, bool>> BasicSearch(string criteria)
{
    // this is just an example, of course
    // NHibernate Linq will translate this to something like 
    // 'WHERE a.MyProperty LIKE '%@criteria%'
    return a => criteria.Contains(a.MyProperty); 
}

用法:

from a in Session.Query<A>().Where(A.BasicSearch(criteria))

更新:显然NHibernate会出现问题。请参阅this blog post for a version that ought to work

答案 1 :(得分:1)

可以调用自己的和SQL函数,但是必须为它们创建一个包装器,以便NHibernate知道如何将C#转换为SQL。

Here's an example我写了一个扩展方法来访问SQL Server的NEWID()函数。您将使用相同的技术来访问数据库服务器上的任何其他函数,内置或用户定义。

答案 2 :(得分:1)

答案 3 :(得分:0)

声明BasicSearch扩展方法。假设您的udf在dbo上:

using NHibernate.Linq;

...

public static class CustomLinqExtensions
{
    [LinqExtensionMethod("dbo.BasicSearch")]
    public static bool BasicSearch(this string searchField, string pattern)
    {
        // No need to implement it in .Net, unless you wish to call it
        // outside IQueryable context too.
        throw new NotImplementedException("This call should be translated " +
            "to SQL and run db side, but it has been run with .Net runtime");
    }
}

然后在您的实体上使用它:

session.Query<A>()
    .Where(a => a.SomeStringProperty.BasicSearch("yourPattern") == true);

注意,尝试在不使用实体的情况下使用它将导致使用.Net运行时进行评估,而不是将其转换为SQL。

将此BasicSearch示例适用于它必须处理的任何输入类型。您的问题是直接在实体上调用它,这不允许您的读者知道需要运行多少列和哪些类型。