我一直致力于使用Nhibernate过滤数据的通用解决方案。代码如下所示:
private ICriteria GetPagedCriteria<T>(GridResult<T> GridResult, bool sort)
{
var query = Session.CreateCriteria(typeof(T));
foreach (string alias in GridResult.NHibernatePaths)
{
query.CreateAlias(alias, alias.Replace(".", "_"));
}
foreach (PropertyValueOperators pvo in GridResult.FilterList)
{
if(String.IsNullOrEmpty(pvo.Value) == false)
{
switch (pvo.LikeOperator)
{
case "Contains":
query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("%{0}%",pvo.Value), MatchMode.Exact));
break;
case "EndsWith":
query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("%{0}", pvo.Value), MatchMode.Exact));
break;
case "Equals":
query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), pvo.Value, MatchMode.Exact));
break;
case "Starts With":
query.Add(Expression.InsensitiveLike(Projections.Cast(NHibernateUtil.String, Projections.Property(pvo.Property)), String.Format("{0}%", pvo.Value), MatchMode.Exact));
break;
default:
throw new ArgumentException("LikeOperator not recognised");
}
}
}
if (sort)
{
foreach (var pair in GridResult.SortList)
{
var func = pair.Value
? new Func<string, NHibernate.Criterion.Order>(NHibernate.Criterion.Order.Asc)
: new Func<string, NHibernate.Criterion.Order>(NHibernate.Criterion.Order.Desc);
query.AddOrder(func(pair.Key));
}
}
return query;
}
不幸的是,这会产生很多“喜欢”和“强制转换”的SQL,效率非常低。据我所知,我知道......我还不是NHibernate的专家,所以我希望任何评论能让这个通用解决方案更有效率。非常感谢提前。
基督教
答案 0 :(得分:2)
在你的情况下,如何避免使用like运算符。 好吧,平等操作员很简单, “以”转换为“喜欢'值'%'的”开头“也是有效的,因为它是左侧匹配并且它可以使用索引, “包含”和“以...结尾”必须转换为您已经实施的类似操作。
如果你真的想避免基于类似的搜索,你必须改变你的方法 - 不要使用CriteriaAPI并将Lucene.NET与NHibernate.Search结合使用,这可能会更好地满足你的需求。我没有在生产项目中使用它们,但它们看起来很完美。
答案 1 :(得分:1)
包含,Endswith和Startswith无法在没有类似的情况下转换为sql中的类似内容。 sql数据库不适合这类查询。您可以更好地使用像Lucene这样的搜索数据库,结合NHiberante.Search