Я пытаюсь создать метод, который создает предикат 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). И кстати, для проверки этой проблемы, этот последний вызов возвращает еще одно "всегда верное" выражение.
Кто-нибудь помогите пожалуйста... Я схожу с ума!