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

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

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

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

  • Как ты строит ваши запросы к базе данных?
  • Предлагает ли C# простой способ динамического построения запросов?
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
13 443
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

LINQ - это то, что вам нужно.

Вы можете рассмотреть LINQ или O / R Mapper, подобный этому: http://www.llblgen.com/

Ответ принят как подходящий

Я использовал 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 () в последнем операторе.

Как связка операторов IF является динамическим запросом?

Esteban Araya 15.09.2008 19:38

IQueryable <Log> преобразуется в SQL в последней строке, где фактически выполняется запрос; все операторы Where LINQ превращаются в одно предложение SQL WHERE. Таким же образом я и делаю SQL с большим разнообразием. Это намного чище, чем пытаться написать для этого сохраненную процедуру.

Ryan Lundy 15.09.2008 19:41

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

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

            }
        );
    }

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

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

public IQueryable<ClientEntity> GetClientsWithWebAccountId(int webAccountId)
    {
        var criteria = PredicateBuilder.True<ClientModel>();
        criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId));
        return GetClients(criteria);
    }

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

Да, мы уже рассмотрели это, но на самом деле это не работает, поскольку наши запросы меняются слишком сильно ...

Ben 15.09.2008 19:36

Если вы используете C# и .NET 3.5, с добавлением MS SQL Server, то LINQ to SQL определенно лучший вариант. Если вы используете что-то другое, кроме этой комбинации, я бы порекомендовал ORM-маршрут, например nHibernate или Дозвуковой.

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

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

:)

// W

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

the fairly complex sql statement (~10 joins, >10 sub selects, ~15-25 where conditions and GroupBy's)

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

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

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

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

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

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

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

Как решить, какие критерии обрабатывать в базе данных, а какие - в linq? Используйте свое суждение. Если вы можете эффективно обрабатывать сложные запросы к базе данных, вы справитесь с этим. Отчасти искусство, отчасти наука.

То, что вы говорите, позволяет БД делать то, в чем она хороша? Я думаю, что работа с linq KristoferA очень впечатляет. С другой стороны, мне больше нравится контролировать производительность базы данных с помощью некоторого транзакционного SQL. Обратите внимание, что уровень абстракции для базы данных может быть набором классов. Подход linq кажется подходом к общему программированию, но на самом деле тогда вам потребуется среда linq для оптимального управления запросами. Так что, хотя технически он впечатляет, он кажется немного непрозрачным, как минимум, и мои производственные среды все равно помещают этот материал в хранимые процессы.

polyglot 26.12.2009 15:48

@polyglot Да, здесь существует огромное количество факторов, и каждый из нас дал бы более конкретный совет, если бы у нас было больше конкретики. Для сложной поисковой системы я делаю хорошая догадка, основываясь на своем опыте, что это все спектакль и ремонтопригодность. Использование динамики в примерах KristoferA может иметь ограничение производительности, которое перевешивает ее гибкость. Linq to generic enumerables обеспечивает простоту по приемлемой цене, если уже проделана некоторая тяжелая работа. И с чрезвычайно сложной логикой я не доверяю Linq-to-sql эффективно настроить работу с базами данных. Еще нет.

Patrick Karcher 31.12.2009 19:10

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

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

Другие вопросы по теме