我可以通过T.Property吗?还有,改进这种方法的想法?

时间:2009-06-18 15:16:22

标签: c# .net nhibernate .net-3.5 orm

或者可能有更好的方法。

我正在为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);
    }

好的,很棒,但是......这里有两件事会造成问题:

  1. 这个查询只处理“和”,我最初的想法就是建立一个动态构建字典的方法,该字典采用属性名称,值和运算符“和”或“或”构建字典以及一系列运算符。这听起来像是正确的事吗?

  2. 好的,所以,这很有效,但是,当有一个整数时,由于单引号而失败。我认为最好的方法是让字典接受<T.Property, string>然后反映到T.Property中以找到数据类型并相应地表现。我是不是太复杂了?

  3. 谢谢。

5 个答案:

答案 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