2009-06-18 67 views
5

或者可能有更好的方法。我可以通过T.Property吗?另外,改进这种方法的想法?

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

OK,很好,但是....有在这里两件事情会引发问题:

  1. 这个查询只处理“和”我最初的思想是通过构建一个方法来动态构建带有属性名称,值和运算符“and”或“or”的字典,并与运算符数组一起构建字典。这听起来像是正确的事情吗?

  2. 好吧,所以,这个工程伟大,但是,当有一个整数,它因为单引号失败。我认为最好的方法是让字典接受<T.Property, string>,然后反映到T.Property中查找数据类型并相应地执行。我是否过分复杂呢?

谢谢。

回答

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); 
} 
+0

我用这个只是我废除了解释一起,只是增加了“财产”字符串到QueryObject类。谢谢! – 2009-06-18 16:34:37

1

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

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

那么,有你的方法把这些类型,而不是一个字典的集合。这样,你可以很容易地检查你是否需要做和/或,以及检查你是否需要报价...

1

我的最初想法是,创造这样的东西不是太明智。您正在编写生成HQL的代码。而后者又被传递给生成SQL的nhibernate。

我建议看看NHibernate criteria查询。首先作为动态构建NHibernate查询的一种更简单的方法。但也给你一些关于滚动你自己的动态查询生成器可能有多复杂的想法。

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

这个问题的更一般的解决方案是抽象您的数据访问,以便如果您想切换ORM,那么您只需更改抽象背后的代码。这当然是更多的工作,但我不相信保持数据访问代码ORM独立是非常重要的。

+0

标准查询是一个很好的方法,但我仍坚持我目前的设置,本着“让我完成”的精神, – 2009-06-18 16:35:28

0

那么你正在做的另一种选择是传递一个Expression>而不是字典,然后解析Linq表达式以获取所需内容。我会做的一个小建议是使用Criteria查询而不是HQL。当然,解析Linq表达式可能比你在这里的要复杂得多。

你也许能够处理字典并做出很好的HQL,但是这样做会让我头脑发热。标准查询似乎是为这类事情设计的。

相关问题