2009-02-23 2 views
18

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

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

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

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

Спасибо!

ответ

24

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

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

Марк

+1

Я использовал этот подход, и мне это нравится. В отличие от большинства людей, я не согласен с тем, что я могу менять код «на лету» во время выполнения, даже простые инструкции SQL, поэтому тот факт, что он скомпилирован вместе с сборкой, является для меня плюсом. – Chris

+1

Рад услышать, что этот подход используется и приветствуется другими! :-) И я согласен - иногда выпечка в ваши скомпилированные биты - плюс. –

+3

Вместо namespacePart используйте this.GetType(). Пространство имен для текущей, динамической версии и typeof (Program) .Namespace для static. Конечно, когда вы ставите его в класс программы как статический. Не забывайте, что, когда ваш SQL-файл находится в каталоге SQL, обратитесь к нему с помощью «SQL.StatementName.sql». – Harry

1

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

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

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

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

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

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

+2

OO Пуристский язык вызывает OO кошмары, как это! веселая! – Steve

1

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

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

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

     //etc.... 
} 
+0

У вас не может быть перегрузок, которые отличаются только возвращаемым типом - это даст ошибку компилятора CS0111 – MattDavey

2

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

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

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

9

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

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

+0

Мне тоже нравится это решение. Сгенерированные свойства удобны. – Steve

1

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

0

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

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

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

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

0

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

0

Glad you asked! Put your sql in a QueryFirst .sql template.

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

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

Смежные вопросы