或者可能有更好的方法。
我正在为NHibernate构建一个动态查询构建器,我们不希望将HQL直接放入应用程序中,我们希望它尽可能与ORM无关。它现在看起来像这样:
public override IEnumerable<T> SelectQuery(Dictionary<string, string> dictionary)
{
string t = Convert.ToString(typeof (T).Name);
string criteria = string.Empty;
foreach (KeyValuePair<string, string> item in dictionary)
{
if (criteria != string.Empty)
criteria += " and ";
criteria += item.Key + " = '" + item.Value + "'";
}
string query = " from " + t;
if (criteria != string.Empty)
query += " where " + criteria;
return FindByHql(query);
}
好的,很棒,但是......这里有两件事会造成问题:
这个查询只处理“和”,我最初的想法就是建立一个动态构建字典的方法,该字典采用属性名称,值和运算符“和”或“或”构建字典以及一系列运算符。这听起来像是正确的事吗?
好的,所以,这很有效,但是,当有一个整数时,由于单引号而失败。我认为最好的方法是让字典接受<T.Property, string>
然后反映到T.Property中以找到数据类型并相应地表现。我是不是太复杂了?
谢谢。
答案 0 :(得分:3)
这样的事情怎么样?
您有手术枚举的地方。您不是传递字典的字符串,而是传递一种QueryObject,它具有值的类型和值的操作。你可以在下面看到。
public enum Operation
{
And,
Or
}
public class QueryObject
{
public string Value { get; set; }
public Type Type { get; set; }
public Operation Operation { get; set; }
}
public override IEnumerable<T> SelectQuery(Dictionary<string, QueryObject> dictionary)
{
string t = Convert.ToString(typeof(T).Name);
string criteria = string.Empty;
foreach (KeyValuePair<string, QueryObject> item in dictionary)
{
if (!string.IsNullOrEmpty(criteria))
{
switch (item.Value.Operation)
{
case Operation.And:
criteria += " and ";
break;
case Operation.Or:
criteria += " or ";
break;
default:
break;
}
}
if (item.Value.Type == typeof(int))
{
criteria += item.Key + " = " + item.Value + " ";
}
else
{
criteria += item.Key + " = '" + item.Value + "'";
}
}
string query = " from " + t;
if (criteria != string.Empty)
query += " where " + criteria;
return FindByHql(query);
}
答案 1 :(得分:1)
我建议创建一个具有所需属性的类:
Name,
Value,
Type,
JoinType (possibly an enum with Or / And)
然后,让您的方法采用这些类型的集合而不是字典。这样,您可以轻松检查是否需要做和/或检查是否需要报价......
答案 2 :(得分:1)
我的初衷是,创造这样的东西并不太明智。您正在编写生成HQL的代码。然后将其传递给生成SQL的nhibernate。
我建议您查看NHibernate criteria查询。首先,作为动态构建NHibernate查询的更简单方法。但是也要给你一些关于如何复制你自己的动态查询构建器的想法。
那就是说。如果我这样做,我可能会使用NHibernate Criteria作为任何类型的动态查询构建器的基础。没有理由不能生成另一个ORM使用的查询。
这个问题的一般解决方案是抽象数据访问,这样如果你想切换ORM,那么你只需要改变抽象背后的代码。当然,这是更多的工作,但我不相信保持您的数据访问代码ORM独立是特别重要的事情。
答案 3 :(得分:0)
你正在做的另一种选择是传递一个表达式&gt;而不是字典,然后解析你想要的Linq表达式。我要做的一个小建议是使用Criteria查询而不是HQL。当然,解析Linq表达式可能比你在这里复杂得多。
你或许可以处理字典并制作出色的HQL,但是这样做会让我头疼。 Criteria查询似乎是为这类事情设计的。
答案 4 :(得分:0)
如果您要使用Criteria API,则已经存在“按示例查询”(又称QBE)功能,该功能使用实体属性来生成查询。
看一下第12.6节:
https://www.hibernate.org/hib_docs/nhibernate/html/querycriteria.html