【发布时间】:2011-01-04 11:06:26
【问题描述】:
我正在尝试创建一个方法来创建 where 谓词,以便稍后在 linq where 方法 (Linq2NHibernate) 上使用。 我这里有一个方法,它执行创建将在查询 Linq 中使用的表达式。 让我们看一些代码
private Expression<Func<Model.FattureEmesse, bool>> getUserFilterExpression(FattureFilter filterStructure)
{
Expression<Func<Model.FattureEmesse, bool>> dataDocumentoFilter = f =>
true;
Expression<Func<Model.FattureEmesse, bool>> dataFineValiditaFilter = f =>
true;
var userFilterExpression = dataDocumentoFilter
.And(dataFineValiditaFilter)
.And(dataImportazioneFilter);
return userFilterExpression;
}
该表达式将比简单的“始终正确”更复杂,但对于我遇到的问题,我得到了相同的行为。 .And 你看到的是一种扩展方法(我在 SO 上找到了真实的)
internal static class PredicateExtensions
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) where T : Model.DomainModelObject
{
InvocationExpression invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
}
}
现在我有一个业务逻辑类,其中包含一个收集创建的表达式并将其传递给 DAL 管理器的方法。 该方法只是调用
var userFilterExpression = getUserFilterExpression(filterStructure);
var securityFilterExpression = new BL.SecurityManager().getFilterExpression<Model.FattureEmesse>(user);
var totalFilterExpression = userFilterExpression.And(securityFilterExpression);
如您所见,我从 Securitymanager 中检索了另一个表达式(如果您怀疑,即使我避免将 2 表达式链接在一起,也会出现问题) 然后调用
var filteredFatture = new GenericDalManager().getFilteredList<Model.FattureEmesse>(maximumRows, startRowIndex, totalFilterExpression);
这是将所有内容放在一起进行查询的地方
public class GenericDalManager
{
internal IList<T> getFilteredList<T>(int maximumRows, int startRowIndex, Expression<Func<T, bool>> expressionResult) where T : Model.DomainModelObject
{
using (var session = PersistenceManager.Istance.GetSession())
{
var items = (from o in session.Linq<T>()
orderby o.Id
select o);
var filteredItems = items.Where(expressionResult)
.Skip(startRowIndex)
.Take(maximumRows);
return filteredItems.ToList();
}
}
}
所以,当我调用执行查询的方法时,它会在最后一行看到的 .ToList() 调用中返回错误。 错误是 你调用的对象是空的。 它发生在 NHibernate.Linq 中。 这个问题似乎与 And 扩展方法有关,因为如果我做一个简单的表达式,没有任何链接,它就可以工作。 怎么了? 如果我在将表达式传递给 genericDalManager.getFilteredList 方法之前简单地编译表达式,一切正常,但它不会将表达式评估为数据库上的查询(显然“始终为真”表达式不会生成任何有趣的 where 子句,但是我需要这个工作才能做一些更复杂的过滤器)。 奇怪的是,如果我不在 getUserFiltreExpression 方法中链接两个“始终为真”的表达式,但我只返回第一个,一切正常。即使在相同的表达式之后将与 BL.SecurityManager().getFilterExpression(user) 调用的结果链接。 顺便说一句,为了测试这个问题,最后一次调用返回另一个“始终为真”的表达式。
请大家帮忙...我快生气了!
【问题讨论】:
标签: nhibernate .net-4.0 lambda expression-trees linq-to-nhibernate