Где вы размещаете операторы SQL в своих проектах на c #? - PullRequest
22 голосов
/ 23 февраля 2009

Я, вероятно, буду отвечать за перенос приложения vb6 на c #. Это приложение для Windows, которое взаимодействует с БД доступа. Доступ к данным инкапсулирован в базовые бизнес-объекты. Один класс для одного стола в принципе. Существующие бизнес-объекты vb6 читают и записывают в БД через DAO. Я уже писал DAL и ORM несколько раз, но все они предназначались только для SQL Server. Это будет необходимо для целевого доступа и сервера SQL. В предыдущих проектах я помещал строки SQL в частные части бизнес-объекта и, возможно, перемещал избыточный код sql, например соединение, создание команды, в общий базовый класс для сокращения кода.

На этот раз я думаю о записи строк SQL в файл .settings или какой-либо другой текстовый файл типа ключ / значение. Затем я написал бы утилиту sql для редактирования этого файла и позволил бы мне запускать и тестировать параметризованные запросы. На эти запросы будет ссылаться по имени в бизнес-объекте вместо встраивания sql в код.

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

Итак, вы, ребята, делаете такие вещи? Как бы вы подошли к этой проблеме? Что работает лучше для вас?

Спасибо!

Ответы [ 9 ]

32 голосов
/ 23 февраля 2009

Ну, есть много вариантов - так что это действительно зависит от ваших самых насущных потребностей: -)

Одним из подходов может быть создание операторов SQL в виде текстовых файлов внутри вашего решения VS и пометить их как «встроенный ресурс» в «действии сборки». Таким образом, SQL включается в полученную сборку и может быть извлечен из него во время выполнения с помощью ResourceManifestStream платформы .NET:

private string LoadSQLStatement(string statementName)
{
    string sqlStatement = string.Empty;

    string namespacePart = "ConsoleApplication1";
    string resourceName = namespacePart + "." + statementName;

    using(Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        if (stm != null)
        {
            sqlStatement = new StreamReader(stm).ReadToEnd();
        }
    }

    return sqlStatement;
}

Вам необходимо заменить «ConsoleApplication1» фактическим пространством имен, в котором находятся файлы операторов sql. Вы должны ссылаться на них с помощью полного имени. Затем вы можете загрузить свой оператор SQL с помощью этой строки:

string mySQLStatement = LoadSQLStatement("MySQLStatement.sql");

Однако это делает запросы довольно «статичными», например Вы не можете конфигурировать и изменять их во время выполнения - они запекаются прямо в скомпилированные двоичные биты. Но с другой стороны, в VS у вас есть хорошее четкое разделение между программным кодом C # и операторами SQL.

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

Марк

10 голосов
/ 23 февраля 2009

Когда мне это действительно нужно, я помещаю запросы в отдельные файлы * .sql, а затем включаю их в Resources.resx. В нем есть раздел «Файлы», который позволяет включать файлы встроенных ресурсов.

После этого я могу использовать сгенерированное свойство Resources.MyQuery, которое гарантирует, что ресурс существует, и избавляет меня от написания пользовательского метода загрузки ресурса.

2 голосов
/ 23 февраля 2009

LINQ to DataSet звучит как путь для вас.

Если вы не использовали .NET 3.5 до / LINQ, тогда вас ждет угощение. LINQ избавит вас от написания исходного кода SQL в строковых литералах и предоставит вам более логичный способ создания запросов.

В любом случае, проверьте эту ссылку для использования баз данных LINQ on Access - http://msdn.microsoft.com/en-us/library/bb386977.aspx

1 голос
/ 23 февраля 2009

Если бы мне нужно было создать приложение для SQL и Access, я бы использовал некоторый интерфейс IDAL, DALCommon с реализацией общей функциональности и отдельные DALSql и DALAccess, унаследованные от DALCommon, с некоторыми конкретными вещами, такими как исключения, обработка транзакций , безопасность и т. д.
Я использовал для хранения имен хранимых процедур или запросов в файлах ресурсов.

1 голос
/ 23 февраля 2009

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

class ConnectToSQL()
{
        //connectSql code (read from setting file i assume)

        XMLDataDocument runProcedure(string procedureName);
        int runProcedure(string procedureName);

        //etc....
}
1 голос
/ 23 февраля 2009

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

  • Базовый класс, в котором объявлены защищенные статические переменные-члены для операторов SQL с нулевым значением, с методом get, который возвращает отдельные операторы SQL

  • Подкласс для каждого поддерживаемого сервера базы данных с методом init, который присваивает переменным члена базового класса

  • Несколько классов DA, ​​которые используют метод базового класса для извлечения операторов SQL

  • Класс запуска приложения, отвечающий за создание правильного объекта подкласса и вызов его метода init

Я также не буду объяснять, почему я не буду этого делать: -)

0 голосов
/ 06 октября 2016

Рад, что вы спросили! Поместите свой sql в шаблон QueryFirst .sql.

Он автоматически компилируется в ваше приложение как встроенный ресурс, но вам все равно. Вы просто пишете это в реальном окне sql, подключенном к вашей БД, с проверкой синтаксиса и intellisense для таблиц и столбцов, а затем используете его через сгенерированные методы Execute() с intellisense для ваших входных данных и результатов.

отказ от ответственности: я написал QueryFirst.

0 голосов
/ 16 июня 2013

Решения по встраиванию, показанные выше, могут не работать, если SQL-запрос имеет причину «где», но для того же самого запроса при следующем запуске требуется PropertyID = '113', поскольку PropertyID считывается.

0 голосов
/ 08 марта 2009

Иногда, как и в пользовательских приложениях для создания отчетов, вам действительно необходимо учитывать несоответствие импеданса и уделять особое внимание SQL. В этих случаях я рекомендую следующее: Для каждого модуля, который содержит строки SQL, создайте один статический класс «SQL» для хранения их всех. Для некоторых строк SQL, вероятно, потребуются параметры, поэтому соблюдайте согласованность и поместите каждую строку в собственный статический метод.

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

В этих случаях я не вижу необходимости скрывать SQL в ресурсах или где-либо еще. Когда важен SQL, тогда это важно. Интересно, что все больше и больше разработчиков теперь свободно смешивают SQL с C #, в том числе, я полагаю, этот сайт, потому что, по сути, это и есть LINQ.

Наконец, как всегда, убедитесь, что вы не подвержены атакам SQL-инъекций. Особенно, если задействован пользовательский ввод, убедитесь, что вы используете какую-то параметризацию и что вы не используете конкатенацию строк.

...