我想在我的基础知识库类中添加一个方法,允许我使用 LIKE 表达式,但我不太清楚如何解决这个问题。我想创建一个泛型方法,查看传入的表达式树,并在传入的字符串值中查找通配符。然后它会相应地生成QueryOver
语句。
我目前有以下内容:
public IList<T> FindAll(Expression<Func<T, bool>> criteria, char wildCard)
{
return SessionFactory.GetCurrentSession()
.QueryOver<T>()
.Where(criteria)
.List();
}
显然,困难的部分尚未到来。我需要查看表达式树并动态地使用QueryOver
构建查询。寻找关于如何继续这一点的一些指示。或者我只是在这里浪费时间,应该在我的存储库中创建处理 LIKE 查询的单个方法?
理想情况下,我想区分以下内容:
因此生成的查询将是:
答案 0 :(得分:13)
在QueryOver中编写Like表达式有两种方法。
如果你从Where子句中删除它:
.Where(Restrictions.Like(Projections.Property<T>(*projected property*), *string value*, MatchMode.Anywhere))
然而这写起来有点长。
所以你可以使用WhereRestrictionOn:
.WhereRestrictionOn(*projected property*).IsLike(*string value*, MatchMode.Anywhere)
这意味着你需要传递两个参数,如:
FindAll<User>(x => x.FirstName, "bob");
您可以使用.Contains,.StartsWith,.EndsWith,但我不确定。
FindAll<User>(x => x.FirstName.Contains("bob"));
FindAll<User>(x => x.FirstName.StartsWith("bob"));
FindAll<User>(x => x.FirstName.EndsWith("bob"));
我认为这些不适用于NHibernate。
希望有所帮助。
答案 1 :(得分:0)
我真的不明白你想做什么。您想要查询,例如
session.QueryOver<T>().Where(x => x.property == "*substring*").List();
生成属性LIKE“%substring%”查询?在大多数Linq提供程序中,String.Contains方法在“LIKE”查询中进行转换,因此您不需要在表达式树中查找通配符,仅用于String.Contains方法。
如果是后者,则必须解析表达式树以查找String.Contains()方法。这可能非常麻烦(http://msdn.microsoft.com/en-us/library/bb397951.aspx)。另外,我在你的方法中看不到哪个属性与LIKE运算符“比较”。
无论如何,我认为将ICriterion传递给.Where()更容易,例如
.Where(new NHibernate.Criterion.LikeExpression("property", "%value%"))
,然后用.And()追加你的其他条件。缺点是丢失强类型查询。
答案 2 :(得分:-1)
挖掘一段时间后,找出关于翻译表格表达式问题的解决方案
session.QueryOver<T>().Where(x => x.StringAttrbute.StartsWith("ajoofa"))
到表格的SQL
SELECT * FROM {table} WHERE {string_attribute} LIKE 'ajoofa%'
我想出了以下解决方案:Yu必须为标准字符串函数注册自定义方法调用.Contains(),. StartWith,.EndsWith()。 上帝知道为什么这些函数在NHibernate中没有默认注册。以下代码可以帮助您。
/// Perform the registration of custom methods
/// </summary>
public static void Register()
{
if (!_registered)
{
_registered = true;
String str = null;
ExpressionProcessor.RegisterCustomMethodCall(() => str.StartsWith(null), ProcessStartsWith);
ExpressionProcessor.RegisterCustomMethodCall(() => str.EndsWith(null), ProcessEndsWith);
ExpressionProcessor.RegisterCustomMethodCall(() => str.Contains(null), ProcessContains);
}
}
static ICriterion ProcessStartsWith(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]) + "%";
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}
static ICriterion ProcessEndsWith(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = "%" + ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}
static ICriterion ProcessContains(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = "%" + ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]) + "%";
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}