Универсальный построитель SQL .NET

Я ищу способ написать оператор SQL на С#, ориентированный на разных поставщиков. Типичным примером дифференциации операторов SQL является LIMIT в PostgreSQL и . ТОП в MSSQL.

Это единственный способ решить SQL-синтаксис, подобный двум приведенным выше, чтобы написать операторы if в зависимости от того, какой провайдер выбирает пользователь, или использовать операторы try catch в качестве управления потоком (LIMIT не работает, вместо этого я попробую TOP< /эм>)? Я видел метод LINQ Take, но мне интересно, можно ли это сделать без LINQ?

Другими словами, есть ли в C# некий универсальный класс поставщика SQL, который мне не удалось найти и который можно использовать?


person Patrick    schedule 30.05.2010    source источник
comment
Почему вы не хотите использовать LINQ?   -  person Mark Byers    schedule 30.05.2010
comment
Есть много способов решить эти различия, вы уверены, что использование SQL — это способ сделать это, то есть найти какую-то систему, которая позволит вам написать один оператор SQL, который будет работать с разными поставщиками?   -  person Lasse V. Karlsen    schedule 30.05.2010
comment
@Mark Byers: Ну, я часто нацеливаюсь на .NET 2, и, насколько мне известно, LINQ там не так хорошо работает. Исторически это было потому, что я хотел иметь возможность портировать на Mono без каких-либо проблем, а потом я просто застрял. Поскольку Mono в настоящее время хорошо работает с LINQ, я не могу дать другого хорошего ответа, почему я все еще живу прошлым.   -  person Patrick    schedule 30.05.2010
comment
@Lasse V. Karlsen: Как мне получить данные из базы данных SQL на C# без использования оператора SQL? У вас есть пример системы, в которой я могу устранить различия?   -  person Patrick    schedule 30.05.2010
comment
Нет, я не это имел в виду. Вы можете настроить систему, в которой вам фактически придется написать два оператора SQL, каждый со своей собственной оптимизацией для разных механизмов баз данных, а затем просто наложить их друг на друга, чтобы коду, который их использует, не нужно было знать, какой из них является в настоящее время используется. Здесь можно использовать контейнер IoC или аналогичный. Однако, если вы хотите/нужно пойти по пути одного sql, ориентированного на разных провайдеров, то я пошел по этому пути и мог бы иметь для вас некоторый код.   -  person Lasse V. Karlsen    schedule 30.05.2010


Ответы (5)


Entity Framework может ориентироваться на разные базы данных. Это позволит вам написать операторы LINQ, которые будут работать с обеими базами данных. Вам нужно будет найти поставщика postgresql для Entity Framework. Есть несколько на выбор.

Надеюсь это поможет.

person Joel Cunningham    schedule 30.05.2010

Существует DBLinq:

Поставщик LINQ для Oracle, PostgreSQL, MySQL, Ingres, SQLite, Firebird и... SQL Server (C# 3.0)

При создании запроса с использованием LINQ to SQL можно просмотреть сгенерированный SQL и сохранить его.

Однако это не соответствует вашему требованию «без использования LINQ». Если у вас есть доступный LINQ, почему бы не использовать его?

person Mark Byers    schedule 30.05.2010

Я не думаю, что существует «универсальный провайдер SQL».

В нашем магазине нам необходимо поддерживать как DB2, так и SQL Server, поэтому мы решили реализовать шаблон уровня, создающий классы модели, доступа к данным и бизнес-логики. Уровень доступа к данным обрабатывает подключение к различным СУБД и загружает классы моделей, передавая их обратно в бизнес-логику. Бизнес-логика и классы модели понятия не имеют, откуда уровень доступа к данным получает данные.

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

person Marc Tidd    schedule 30.05.2010
comment
Ой, мой первый голос против. Объяснение будет оценено. Спасибо. - person Marc Tidd; 30.05.2010
comment
Так в основном, реализовать свой собственный? :-) Насколько мне известно, хранимые процедуры не являются стандартом среди баз данных, хотя это и хороший момент, поскольку они уменьшают количество ошибок, которые могут возникнуть при работе с бизнес-логикой. Я искал способ, например, составить список таблиц в базе данных, а затем получить столбцы из конкретной таблицы в любой базе данных, и в этом случае SP не так уж хороши. - person Patrick; 30.05.2010
comment
Я вижу, в вашем вопросе не подробно описано требование обнаружения объектов базы данных, это выходит далеко за рамки различий в реализациях SQL. Спасибо за объяснение, и я понимаю, что это не то, что вы ищете, и, следовательно, голосование против. - person Marc Tidd; 30.05.2010
comment
Я не минусовал. Я ценю ответ и думаю, что это был хороший ответ, учитывая требования, которые я указал в своем вопросе. - person Patrick; 30.05.2010
comment
@ Патрик, я предполагал, что ты отвечаешь на мою просьбу о разъяснении. В любом случае спасибо за отзыв. - person Marc Tidd; 30.05.2010

Присоединяюсь к идее Марка Тидда. Если вам не нужен Linq, создайте отдельные классы DAL для каждого провайдера или используйте хранимые процедуры, которые будут реализованы в каждой БД.

person rkellerm    schedule 30.05.2010
comment
Да, основная идея решения проблемы SQL заключается в использовании хранимых процедур, вам не нужно проходить весь шаблон слоя, если он не подходит для вашего решения. - person Marc Tidd; 30.05.2010

По какой-то причине мне не нравится linq как интерфейс запросов, и некоторое время назад я начал создавать библиотеку для генерации sql. Посмотрите на LambdaSql. На данный момент он содержит базовые сценарии для предложения select и фильтров where. Поля настройки, где, группировать, иметь, упорядочивать, объединять, вложенные запросы уже поддерживаются. Вставка, обновление и удаление будут поддерживаться позже. Он также содержит некоторые пункты для расширения существующего поведения. Например, Limit реализован таким образом.

Пример:

var qry = new SqlSelect
(
    new SqlSelect<Person>()
        .AddFields(p => p.Id, p => p.Name)
        .Where(SqlFilter<Person>.From(p => p.Name).EqualTo("Sergey"))
    , new SqlAlias("inner")
).AddFields<Person>(p => p.Name);

Console.WriteLine(qry.ParametricSql);
Console.WriteLine("---");
Console.WriteLine(string.Join("; ", qry.Parameters
    .Select(p => $"Name = {p.ParameterName}, Value = {p.Value}")));

Выход:

SELECT
    inner.Name
FROM
(
    SELECT
        pe.Id, pe.Name
    FROM
        Person pe
    WHERE
        pe.Name = @w0
) AS inner
---
Name = @w0, Value = Sergey

Подробнее см. здесь https://github.com/Serg046/LambdaSql

person Serg046    schedule 09.09.2018