【问题标题】:Can I pass in T.Property? Also, ideas for improving this method?我可以通过 T.Property 吗?另外,改进这种方法的想法?
【发布时间】:2009-06-18 15:16:22
【问题描述】:

或者可能有更好的方法。

我正在为 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. 这个查询只处理“and”,我最初的想法是通过构建一个方法来动态构建字典,该字典采用属性名称、值和运算符“and”或“or”并构建字典以及一系列运算符。这听起来像是正确的做法吗?

  2. 好的,所以,这很好用,但是,当有一个整数时,它会因为单引号而失败。我认为最好的方法是让字典接受&lt;T.Property, string&gt;,然后反映到 T.Property 以查找数据类型并采取相应的行为。我是不是把事情复杂化了?

谢谢。

【问题讨论】:

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


    【解决方案1】:

    这样的事情怎么样。

    你有一个操作的枚举。不是为字典传递一个字符串,而是传递一种 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);
    }
    

    【讨论】:

    • 我使用了这个,除了我一起取消了 Dictionary 并且只是将“Property”作为字符串添加到 QueryObject 类中。谢谢!
    【解决方案2】:

    我建议可能创建一个具有您需要的所有属性的类:

    Name,
    Value,
    Type,
    JoinType (possibly an enum with Or / And)
    

    然后,让您的方法采用这些类型的集合,而不是字典。这样,您可以轻松检查是否需要做和/或,以及检查是否需要引号...

    【讨论】:

      【解决方案3】:

      我最初的想法是创建这样的东西不太明智。您正在编写生成 HQL 的代码。依次传递给生成 SQL 的 nhibernate。

      我建议看看 NHibernate criteria 查询。首先,作为动态构建 NHibernate 查询的更简单方法。同时也让您了解滚动您自己的动态查询构建器的复杂程度。

      就是这么说的。如果我这样做,我可能会使用 NHibernate Criteria 作为任何类型的动态查询构建器的基础。它没有理由不能生成另一个 ORM 使用的查询。

      这个问题的一个更通用的解决方案是抽象你的数据访问,这样如果你想切换 ORM,那么你只需要更改抽象背后的代码。这当然是更多的工作,但我不相信保持数据访问代码 ORM 独立是特别重要的事情。

      【讨论】:

      • 标准查询是一个不错的选择,但我本着“完成任务”的精神继续使用我目前的设置
      【解决方案4】:

      你正在做的另一种方法是传递一个 Expression> 而不是字典,然后解析 Linq 表达式以获得你想要的东西。我提出的一个小建议是使用 Criteria 查询而不是 HQL。当然,解析 Linq 表达式可能比你这里的要复杂得多。

      您也许可以处理字典并制作出色的 HQL,但一想到要这样做,我就会头疼。标准查询似乎是为这类事情设计的。

      【讨论】:

        【解决方案5】:

        如果您要使用 Criteria API,那么已经有“通过示例查询”(又名 QBE)功能,它使用实体属性来生成查询。

        看看第 12.6 节:

        https://www.hibernate.org/hib_docs/nhibernate/html/querycriteria.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多