我可以传递 T.Property 吗?另外,有哪些改进此方法的想法?

5

或许有更好的方法。

我正在为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. 好的,这很好用,但是当出现整数时会失败,因为有单引号。我认为最好的方式是让字典接受 <T.Property, string> 然后反射到 T.Property 找到数据类型并进行相应的操作。我是否过于复杂了?

谢谢。

5个回答

2

以下是可能的示例:

您可以为操作创建一个枚举。 代替传递字典的字符串,您可以传递具有值类型和值操作的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);
}

我使用了这个,但是我完全放弃了字典,并将“Property”作为字符串添加到QueryObject类中。谢谢! - Sara Chipps

1
我建议可能创建一个包含您所需属性的类:
Name,
Value,
Type,
JoinType (possibly an enum with Or / And)

然后,让你的方法接受这些类型的集合而不是字典。这样,你就可以轻松地检查是否需要进行 and/or 操作,以及检查是否需要引号...


1

我的初始想法是,创建这样的东西并不太明智。您正在编写生成HQL的代码。然后将其传递给nhibernate,该软件生成SQL。

我建议您查看NHibernatecriteria查询。首先,这是一种更容易动态构建NHibernate查询的方法。但也可以让您对自己动态查询生成器的复杂性有所了解。

话虽如此。如果我在做,我可能会将NHibernate Criteria用作任何动态查询生成器的基础。没有理由不能生成要由另一个ORM使用的查询。

问题的更普遍解决方案是将数据访问抽象化,以便如果要切换ORM,则只需更改抽象化背后的代码。当然,这需要更多的工作,但我不认为保持数据访问代码ORM独立是特别重要的。


查询条件是一个不错的选择,但出于“完成任务”的精神,我仍然坚持使用当前的设置。 - Sara Chipps

0

你可以尝试使用传递Expression>而非字典的替代方法,然后解析Linq表达式以获取所需内容。我建议使用Criteria查询代替HQL。当然,解析Linq表达式可能比你现在做的要复杂得多。

虽然你可以处理字典并生成出色的HQL,但是考虑通过这种方式进行操作会让人头疼。Criteria查询似乎就是为这种事情设计的。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接