Могу ли я пройти в T.Property? Также есть идеи по улучшению этого метода? - PullRequest
5 голосов
/ 18 июня 2009

Или, возможно, есть лучший способ.

Я создаю динамический построитель запросов для 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, чтобы найти тип данных и вести себя соответственно. Я слишком усложняю это?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 18 июня 2009

Как насчет этого?

Где у вас есть перечисление для операции. Вместо передачи строки для словаря вы передаете тип 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 голос
/ 18 июня 2009

Моя первоначальная мысль заключается в том, что создание чего-то подобного не слишком разумно. Вы пишете код, который генерирует HQL. Который, в свою очередь, передается в nhibernate, который генерирует SQL.

Я бы посоветовал взглянуть на NHibernate критерий запросов. Во-первых, как более простой способ динамического построения запроса NHibernate. Но также для того, чтобы дать вам некоторое представление о том, насколько сложным может быть ваш собственный динамический построитель запросов.

Это сказал. Если бы я делал это, я бы, вероятно, использовал бы критерии NHibernate в качестве основы для любого вида динамического построителя запросов. Нет причин, по которым он не может сгенерировать запрос для использования другим ORM.

Более общее решение проблемы состоит в том, чтобы абстрагировать ваш доступ к данным, так что если вы хотите переключить ORM, вам нужно всего лишь изменить код вашей абстракции. Конечно, это больше работы, но я не уверен, что сохранение кода доступа к данным ORM независимым является особенно важным.

1 голос
/ 18 июня 2009

Я бы предложил создать класс со всеми необходимыми вам свойствами:

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

тогда пусть ваш метод использует набор этих типов, а не словарь. Таким образом, вы можете легко проверить, если вам нужно сделать и / или, а также проверить, если вам нужны кавычки ...

0 голосов
/ 22 июня 2009

Если бы вы использовали Criteria API, уже есть функциональность «Запрос по примеру» (или QBE), которая использует свойства сущностей для генерации запросов.

Взгляните на раздел 12.6:

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

0 голосов
/ 18 июня 2009

Хорошо, альтернативой тому, что вы делаете, является передача выражения> вместо словаря, а затем синтаксический анализ выражения Linq для того, что вы хотите. Небольшое предложение, которое я хотел бы сделать, это использовать запрос Criteria вместо HQL. Конечно, разбор выражения Linq, вероятно, намного сложнее, чем у вас здесь.

Возможно, вам удастся обработать словарь и создать великолепный HQL, но мне больно думать, что я так поступаю. Запросы критериев, похоже, предназначены для такого рода вещей.

...