简体   繁体   中英

NHibernate - dynamic QueryOver parameter

I have an MVC project that I'm trying to setup a nice paging solution for.

I have several tables in SQL Server that have several thousand rows that I would like to be able to page through. If I don't have any type of filter to apply to the paging, it works great. This is the method I'm using to do that:

    public virtual PagedList<T> GetPagedData(int startIndex, int count) {
        var rowCount = session.CreateCriteria(typeof(T)).SetProjection(Projections.RowCount()).FutureValue<Int32>().Value;
        var pageOfItems = session.CreateCriteria(typeof(T)).SetFirstResult(startIndex).SetMaxResults(count).List<T>();
        return new PagedList<T>(pageOfItems, startIndex, count, rowCount);
    }

I also want the ability to pass in a query to narrow the results down even further, and return a new paging table. What I have so far is:

    public virtual PagedList<T> GetPagedData<T>(int startIndex, int count, System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T : class {
        var rowCount = session.QueryOver<T>().Where(predicate).Select(Projections.RowCount()).FutureValue<Int32>().Value;

        var pageOfItems = session.QueryOver<T>().Where(predicate).Skip(startIndex).Take(count).List<T>();
        return new PagedList<T>(pageOfItems, startIndex, count, rowCount);
    }

The call to this would look something like this:

networks = mRepository.GetPagedData<Network>(page ?? 1, pageSize, x => x.Name.Contains(q));

The problem is, it doesn't like the "Contains" expression. If I do an exact match, it works fine (x.Name == q), but I don't get the results I'm after.

The exception I'm seeing using "Contains" is:

Unrecognised method call: System.String:Boolean Contains(System.String)

Does anyone have an idea how to get this to accept an expression like this dynamically? I have a base repository class that I've put this in, because I'll use the same type of behavior for several other tables. I could write a separate method for each table, but I would rather do this dynamically if it's possible.

Thanks for any advice!

QueryOver is not LINQ, and it only accepts a very limited set of expressions.

My suggestion is that you rewrite your method to use LINQ, by replacing QueryOver with Query . The only problem is that it's harder to do the Count using a future query (see this answer for details)

Here's a version without Future:

public virtual PagedList<T> GetPagedData<T>(int startIndex, int count,
               Expression<Func<T, bool>> predicate) where T : class
{
    var query = session.Query<T>().Where(predicate);
    var rowCount = query.Count();
    var page = query.Skip(startIndex).Take(count).List<T>();
    return new PagedList<T>(pageOfItems, startIndex, count, rowCount);
}

使用QueryOver ,必须使用扩展方法IsLike ,所以必须使用x.Name.IsLike(q, MatchMode.Anywhere)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM