Лучший способ построения динамических запросов SQL в C # /. NET3.5? - PullRequest
8 голосов
/ 15 сентября 2008

Проект, над которым я сейчас работаю, включает в себя рефакторинг C # Com Object, который служит слоем доступа к базам данных для некоторых баз данных Sql 2005.

Автор существующего кода создал все запросы sql вручную, используя строку и множество операторов if для построения довольно сложного оператора sql (~ 10 объединений,> 10 подвыборов, ~ 15-25, где условия и GroupBy's) , Базовая таблица всегда одна и та же, но структура соединений, условий и группировок зависит от набора параметров, которые передаются в мой класс / метод.

Построение SQL-запроса, подобного этому, работает, но, очевидно, это не очень элегантное решение (и довольно сложное для чтения / понимания и обслуживания) ... Я мог бы просто написать простой "построитель запросов", но я сам Я уверен, что я не первый с такой проблемой, поэтому мои вопросы:

  • Как вы строите запросы к базе данных?
  • Предлагает ли C # простой способ динамически создавать запросы?

Ответы [ 12 ]

9 голосов
/ 15 сентября 2008

Я использовал C # и Linq, чтобы сделать что-то похожее, чтобы фильтровать записи журнала при вводе пользователем (см. Условные запросы Linq ):

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

Редактировать: запрос не выполняется до .ToList () в последнем утверждении.

2 голосов
/ 16 сентября 2008

Если время выполнения действительно не важно, я бы подумал о рефакторинге бизнес-логики, которая (так часто) имеет тенденцию находить путь к слою данных и к хранимым процессам длиной в миллиард С точки зрения поддержки, редактируемости и доступности, я всегда стараюсь (как программист C #) поднять код до бизнес-уровня.

Попытка разобраться с кем-то еще, сценарий SQL из 8000 строк - не моя любимая задача.

:)

// W

1 голос
/ 23 декабря 2009

Я прихожу так поздно, и у меня нет шансов на повышение, но есть отличное решение, которое я не видел, рассматривал: комбинацию процедуры / функции с linq-to-object. Или to-xml или to-datatable, я полагаю.

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

С тех пор я сделал комбинацию функция / процедура и linq . Часто общая сложность меньше, чем сложность попытки сделать это в одном месте. Передайте некоторые из ваших критериев в UDF, которая станет намного более управляемой. Это дает вам управляемый и понятный набор результатов. Примените оставшиеся различия, используя linq.

Вы можете использовать преимущества обоих:

  • Сократить общее количество записей возможно на сервере; получить как можно больше сумасшедшие соединения позаботились о сервер. Базы данных хороши на этом прочее.
  • Линк (к объекту и т. Д.) Не так силен, но отлично подходит для выражения сложных критериев; поэтому используйте его для различных возможных различий, которые усложняют код, но при этом обработка базы данных не будет намного лучше. Работая на сокращенном, нормализованном наборе результатов, linq может выразить соответствие без особых потерь производительности.

Как решить, какие критерии обрабатывать в БД, а какие с помощью linq? Используйте свое суждение. Если вы можете эффективно обрабатывать сложные запросы БД, вы можете справиться с этим. Часть искусства, часть науки.

1 голос
/ 16 сентября 2008

Linq to SQL вместе с System.Linq.Dynamic предоставляет несколько интересных возможностей.

Я разместил здесь несколько примеров кода: http://blog.huagati.com/res/index.php/2008/06/23/application-architecture-part-2-data-access-layer-dynamic-linq

... и здесь: http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/717004553931?r=777003863931#777003863931

1 голос
/ 16 сентября 2008

Я понимаю потенциал Linq, но мне еще предстоит увидеть, как кто-нибудь попытается выполнить запрос Linq о сложности, которую предлагает Бен

довольно сложный оператор SQL (~ 10 объединений,> 10 вложенных элементов, ~ 15-25, где условия и значения GroupBy)

Есть ли у кого-нибудь примеры крупных запросов Linq и комментарии по поводу их управляемости?

1 голос
/ 15 сентября 2008

Стоит подумать, можете ли вы реализовать в качестве параметризованной поточной процедуры и оптимизировать ее в базе данных, а не динамически генерировать SQL через LINQ или ORM во время выполнения. Часто это будет работать лучше. Я знаю, что это немного старомодно, но иногда это самый эффективный подход.

1 голос
/ 15 сентября 2008

Вот как я бы это сделал:

public IQueryable<ClientEntity> GetClients(Expression<Func<ClientModel, bool>> criteria)
    {
        return (
            from model in Context.Client.AsExpandable()
            where criteria.Invoke(model)
            select new Ibfx.AppServer.Imsdb.Entities.Client.ClientEntity()
            {
                Id = model.Id,
                ClientNumber = model.ClientNumber,
                NameFirst = model.NameFirst,
                //more propertie here

            }
        );
    }

Параметр Expression , который вы передадите, будет динамическим запросом, который вы создадите с различными предложениями WHERE, JOINS и т. Д. Это выражение получит Invoided во время выполнения и даст Вы то, что вам нужно.

Вот пример того, как это назвать:

public IQueryable<ClientEntity> GetClientsWithWebAccountId(int webAccountId)
    {
        var criteria = PredicateBuilder.True<ClientModel>();
        criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId));
        return GetClients(criteria);
    }
1 голос
/ 15 сентября 2008

LINQ - это путь.

0 голосов
/ 09 марта 2011

Проверьте http://sqlom.sourceforge.net. Я думаю, что это именно то, что вы ищете.

0 голосов
/ 28 января 2011

Есть своего рода экспериментальная попытка в классе QueryBuilder на http://www.blackbeltcoder.com/Articles/strings/a-sql-querybuilder-class. Может быть стоит посмотреть.

...