我正在尝试执行以下操作:
var query =
(from a in session.Query<A>()
where a.BasicSearch(searchString) == true
select a);
但它一直给我这个异常“System.NotSupportedException”!
知道如何解决这个问题吗?
我正在尝试执行以下操作:
var query =
(from a in session.Query<A>()
where a.BasicSearch(searchString) == true
select a);
但它一直给我这个异常“System.NotSupportedException”!
知道如何解决这个问题吗?
不能在 LINQ 查询中使用用户定义的函数。NHibernate linq 提供程序不“知道”如何将您的函数转换为 SQL。
LINQ to NHibernate 的工作原理是检查您在运行时提供的 LINQ 表达式,并将在此表达式树中找到的内容转换为正则 SQL 表达式。这是一篇了解表达式树背景的好文章:http: //blogs.msdn.com/b/charlie/archive/2008/01/31/expression-tree-basics.aspx
但是,您可以使用此处讨论的技术以另一种方式重用此类谓词。(我不确定这是否适用于 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 会有问题。请参阅此博客文章了解应该可以使用的版本。
可以调用您自己的和 SQL 函数,但您必须为它们制作一个包装器,以便 NHibernate 知道如何将 C# 转换为 SQL。
这是一个示例,我编写了一个扩展方法来访问 SQL Server 的NEWID()
函数。您将使用相同的技术来访问数据库服务器上的任何其他功能,无论是内置的还是用户定义的。
声明一个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
例子适应它必须处理的任何输入类型。您的问题是直接在实体上调用它,这不允许您的读者知道它需要运行多少列以及使用哪些类型。