问题
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!
回答1:
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);
}
回答2:
With the QueryOver
you have to use the extension method IsLike
, so x.Name.IsLike(q, MatchMode.Anywhere)
.
来源:https://stackoverflow.com/questions/5044851/nhibernate-dynamic-queryover-parameter