Цепочка лямбда-выражений .net NHibernate Linq

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

Кто-нибудь помогите пожалуйста... Я схожу с ума!


person themarcuz    schedule 04.01.2011    source источник


Ответы (1)


Я предполагаю, что проблема в том, что вы И с результатом выражения (после вызова), а не с самим выражением. Это выражение, вероятно, не может быть проанализировано. Вам также может понадобиться AndAlso (логическое и) вместо And (побитовое и) и, возможно, перепривязать параметры

person Paco    schedule 04.01.2011