.net NHibernate Linq lambda 表达式链

发布于 2024-10-10 03:12:48 字数 3062 浏览 0 评论 0原文

我正在尝试创建一个方法,该方法创建稍后在 linq where 方法(Linq2NHibernate)上使用的 where 谓词。 我这里有一个方法,用于创建将在查询 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;            
}

表达式将比简单的“始终为真”更复杂,但对于我遇到的问题,我得到了相同的行为。 你看到的是一个扩展方法(我在这里找到了真实的)

 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) 调用的结果链接起来。 顺便说一句,为了测试这个问题,最后一个调用返回另一个“始终为真”表达式。

请任何人帮忙...我很生气!

I'm trying to create a method which create the where predicate to use later on a linq where method (Linq2NHibernate).
what I have here is a method that perform the creation of an expression that will be used in a query Linq.
Let's see some code

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;            
}

The expression will be more complex than a simple "always true", but for the problem I have I got the same behaviour.
The .And you see is an extension method (I found here on SO for real)

 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);
    }
}

Now I have a Business Logic class with a method that collect the Expression created and pass it to the DAL manager.
That method simply calls

var userFilterExpression = getUserFilterExpression(filterStructure);
var securityFilterExpression = new BL.SecurityManager().getFilterExpression<Model.FattureEmesse>(user);
var totalFilterExpression = userFilterExpression.And(securityFilterExpression);

As you can see I retrieve another expression from the Securitymanager (in case you doubt, the problem occour even if I avoid to chain toghether the 2 expression)
and then call

var filteredFatture = new GenericDalManager().getFilteredList<Model.FattureEmesse>(maximumRows, startRowIndex, totalFilterExpression);

This is where everything is put toghether to make the query

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();
      }  
   }
}

So, when I call the method that perform the query, it gaves e back an error in the .ToList() call you see in the last line.
The error is
Object reference not set to an instance of an object.
And it occurs in NHibernate.Linq.
The problem seems to be related to the And extension method, since it works if I make a simple expression, without any chaining.
What's wrong?
If I simply compile the expression befor passing it to the genericDalManager.getFilteredList method, everything works, but it will not evaluate the expression as a query on the database (obviously the "always true" expression won't generate any interesting where clause, but I need this to work in order to do some more complex filter).
The strange thing is that if I won't chain the two "always true" expression in the method getUserFiltreExpression, but I return only the first one, everything works fine. Even if after the same expression will be chained with the result of BL.SecurityManager().getFilterExpression(user) calling.
And by the way, for testing this issue, this last call return another "always true" expression.

Anyone help please... I'm getting mad!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

总攻大人 2024-10-17 03:12:48

我想问题是你 And 与表达式的结果(调用后)而不是表达式本身。该表达式可能无法解析。您可能还需要 AndAlso(逻辑与)代替 And(按位与),并且可能重新绑定参数

I guess the problem is that you And with the result of the expression (after invoke) and not with the expression itself. That expression can probably not be parsed. You might also have to you AndAlso (logical and) insead of And (bitwise and) and maybe rebind the parameters

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文