SQLMetal

20

Хотя еще предстоит рассмотреть разные способы создания сущностных классов, необходимых для использования LINQ to SQL с базой данных, вы должны знать, что простейший путь генерации сущностных классов для всей базы данных, если еще нет бизнес-классов, заключается в применении утилиты SQLMetal. Ее можно найти в каталоге C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools. Утилита SQLMetal — инструмент командной строки, который генерирует все необходимые части сущностных классов LINQ to SQL.

Чтобы увидеть доступные опции программы SQLMetal, откройте окно командной строки Visual Studio, выбрав в меню пункт Microsoft Visual Studio 2010 --> Visual Studio Tools --> Командная строка Visual Studio 2010.

Введите в окне командной строки sqlmetal и нажмите <Enter>:

Команды SQLMetal

Как видите, даже приведено несколько примеров запуска. Доступные опции описаны в таблице ниже:

Опции SQLMetal
Опция/Пример Описание
/server:<имя>
/server:.\SQLExpress
Эта опция позволяет указывать имя сервера базы данных, к которому нужно подключиться. Если ее опустить, SQLMetal принимает по умолчанию localhost/sqlexpress. Чтобы заставить SQLMetal сгенерировать сущностные классы из файла MDF, опустите эту опцию вместе с опцией /database и укажите полное путевое имя MDF-файла в конце команды.
/database:<имя>
/database:Northwind
Это имя базы данных на указанном сервере, для которой генерируются сущностные классы. Чтобы заставить SQLMetal сгенерировать сущностные классы из файла MDF, опустите эту опцию вместе с опцией /server и укажите полное путевое имя MDF-файла в конце команды.
/user:<имя>
/user:Alex
Это пользовательская учетная запись, применяемая для регистрации в указанной базе данных при подключении для создания сущностных классов.
/password:<пароль>
/password:1590597893
Это пароль, используемый указанной пользовательской учетной записью для регистрации в указанной базе данных при подключении для создания сущностных классов.
/conn:<строка подключения>
/conn:"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;"
Это строка подключения к базе данных. Ее можно использовать вместо указания опций /server, /database, /user и /password.
/timeout:<секунды>
/timeout: 120
Эта опция позволяет указывать значение таймаута в секундах для использования утилитой SQLMetal при генерации сущностных классов. Пропуск этой опции аналогичен указанию SQLMetal значения по умолчанию — 0, что означает отсутствие таймаута.
Эта опция не управляет таймаутом сгенерированного класса DataContext, который будет использоваться для запросов LINQ to SQL. Для управления таким таймаутом понадобится устанавливать свойство CommandTimeout класса DataContext или, для более тонкого контроля, вызывать метод DataContext.GetCommand для настройки таймаута конкретного запроса.
/views Указывайте эту опцию для генерации SQLMetal необходимых свойств Table<T> и сущностных классов для поддержки заданных представлений базы данных.
/functions Применяйте эту опцию для генерации SQLMetal методов для вызова указанных пользовательских функций базы данных.
/sprocs Применяйте эту опцию для генерации SQLMetal методов для вызова указанных хранимых процедур базы данных.
/dbml[:файл]
/dbml:Northwind.dbml
Эта опция указывает имя промежуточного DBML-файла. Целью генерации этого файла является управление именами сгенерированных сущностных классов и их свойств.

Благодаря этой опции, можно сгенерировать промежуточный DBML-файл, отредактировать его и затем создать модуль исходного кода вызовом SQLMetal на промежуточном файле DBML с указанием опции /code.

В качестве альтернативы можно загрузить промежуточный DBML-файл, созданный этой опцией, в Object Relational Designer, отредактировать его в визуальном конструкторе и позволить визуальному конструктору сгенерировать необходимый исходный код.

Эта опция не может быть использована вместе с /map.
/code[:файл]
/code:Northwind.cs
Это имя файла, создаваемого SQLMetal, который содержит класс, производный от DataContext, и сущностные классы на указанном языке программирования.

Эта опция не может использоваться вместе с /dbml. Интересно, что если указать обе опции — /code и /map — в одном вызове SQLMetal, то получится код, сгенерированный без атрибутов LINQ to SQL. Конечно, вы должны использовать сгенерированное отображение (map) вместе с генерированным кодом, чтобы иметь возможность применять LINQ to SQL.
/map[:файл]
/map:northwindmap.xml
Эта опция указывает, что SQLMetal должен генерировать внешний XML-файл отображения, в противоположность модулю исходного кода, заданного опцией /code.

Этот внешний XML-файл отображения может затем быть загружен при создании экземпляра DataContext. Это позволяет использовать LINQ to SQL без какого-либо действительного исходного кода LINQ to SQL, скомпилированного вместе с вашим кодом.
/language:<язык>
/language:C#
Эта опция определяет, для какого языка программирования должен генерировать код SQLMetal. Допустимые опции в настоящее время: csharp, C# и VB.
/namespace:<имя>
/namespace:nwind
Эта опция диктует пространство имен, в котором будут находиться сгенерированный класс-наследник DataContext и сущностные классы.
/context:<тип>
/context:Northwind
Указывает имя сгенерированного класса-наследника DataContext.

Если данная опция опущена, имя класса будет совпадать с именем базы данных, для которой генерируется код.
/entitybase:<тип>
/entitybase:MyEntityClassBase
Указывает имя класса, используемого в качестве базового для генерируемых SQLMetal сущностных классов.

Если данная опция опущена, сгенерированные сущностные классы не наследуются ни от какого другого класса.
/pluralize Эта опция заставляет SQLMetal сохранять множественное число в именах таблиц, но единственное — в именах классов, отображенных на эти таблицы. Таким образом, для таблицы базы данных по имени Customers сгенерированный сущностный класс будет назван Customer (в единственном числе), а Table<Customer> будет сгенерирован с именем Customers (во множественном числе). Таким образом, объект Customer хранится в таблице Customers. С грамматической точки зрения это звучит правильно.

Без указания этой опции сущностный класс будет назван Customers (во множественном числе), и Table<Customers> будет назван Customers (во множественном числе). Это значит, что объект Customers буде находиться в таблице Customers. С точки зрения грамматики звучит неверно.
/serialization:<опция>
/serialization:None
Эта опция указывает, должен ли SQLMetal генерировать атрибуты сериализации для классов. Возможные варианты значений — None и Unidirectional.

Если эта опция опущена, по умолчанию SQLMetal принимает None
/provider:<тип>
/provider:SQL2005
Данная опция используется для указания класса поставщика базы данных. Допустимые значения: SQLCompact, SQL2000, SQL2005, SQL2008 и SQL2012. Утилита SQLMetal будет генерировать атрибут Provider с классом, заданным в этой опции.

Каждое допустимое значение отображается на класс поставщика из пространства имен System.Data.Linq.SqlClient. Утилита SQLMetal добавляет строку Provider в конец указанного значения, чтобы получить имя класса поставщика, и генерирует атрибут Provider, определяющий это имя класса поставщика.

Обратите внимание, что опции /dbml, /code и /map могут быть указаны без предоставления имени файла. Если имя файла не задано, то сгенерированный код XML выводится на консоль.

Сравнение XML-файла отображения и промежуточного файла DBML

Одним из запутанных аспектов использования SQLMetal является то, что он позволяет указывать два разных типа выходных XML-файлов. Один создается с помощью опции /map, а второй — посредством опции /dbml.

Отличие между этими двумя файлами состоит в том, что опция /map создает внешний XML-файл отображения, предназначенный для загрузки при создании экземпляра DataContext. Опция /map — альтернатива генерации или написанию вручную исходного модуля, содержащего атрибуты LINQ to SQL, которые компилируются.

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

Это называется "в некоторой степени динамическим обращением", потому что код должен знать имена таблиц и полей; в противном случае он просто не будет знать, что запрашивать. Внешний XML-файл отображения инструктирует LINQ to SQL о том, какие есть таблицы, столбцы и хранимые процедуры, с которыми он может взаимодействовать, и на какие классы, свойства и методы они должны быть отображены.

Опция /dbml создает промежуточный файл DBML (XML) для обеспечения возможности редактирования имен впоследствии генерируемых сущностных классов и их свойств. Затем понадобится сгенерировать модуль исходного кода, запустив SQLMetal снова — на этот раз на файле DBML, а не на базе данных, и указав опцию /code. Или же можно загрузить промежуточный DBML-файл в Object Relational Designer, отредактировать его и позволить визуальному конструктору сгенерировать исходный код необходимых сущностных классов.

Другая причина того, что SQLMetal может генерировать два типа XML файлов — XML-файла отображения и промежуточного DBML-файла — состоит в путанице из-за их сходства. Так что не удивляйтесь, когда увидите, насколько они похожи.

Работа с промежуточным файлом DBML

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

Предполагая, что имеется расширенная база данных Northwind, присоединенная к серверу базы данных SQL Server, вот как можно создать промежуточный файл DBML:

sqlmetal /server:.\SQLExpress /database:Northwind /pluralize /sprocs /functions /views /dbml:Northwind.dbml

Указание опций /server и /database при запуске SQLMetal требует, чтобы расширенная база данных Northwind была присоединена к SQL Server. Вдобавок может понадобиться указать соответствующие опции /user и /password, чтобы SQLMetal мог подключиться к базе данных.

Или же можно сгенерировать промежуточный файл DBML из файла MDF:

sqlmetal /pluralize /sprocs /functions /views /dbml:Northwind.dbml "C:\Northwind.mdf"

Генерация промежуточного файла DBML из файла MDF может потребовать присоединения этого MDF-файла к SQL Server с именем C:\NORTHWIND.MDF или подобным. Для корректной работы примеров необходимо переименовать базу данных в "Northwind" внутри SQL Server Enterprise Manager или SQL Management Studio.

Любой из двух описанных подходов должен привести к генерации идентичных промежуточных DBML-файлов. Указаны только те опции, которые существенны для чтения базы данных и производства DBML-файла. Такие опции, как /language и /code, имеют значение только при создании модуля исходного кода.

Отредактировав промежуточный XML-файл, можно сгенерировать модуль исходного кода следующим образом:

sqlmetal /namespace:nwind /coderNorthwind.cs Northwind.dbml

Опции, которые были заданы при запуске SQLMetal, важны при генерации исходного кода.

Схема промежуточного файла DBML

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

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

Или, что еще лучше — можно загрузить сгенерированный DBML-файл в Object Relational Designer внутри Visual Studio и отредактировать его там. Это средство предоставит графический интерфейс пользователя для манипуляций объектно-реляционной моделью, а также избавит от необходимости знания и понимания схемы. В следующей статье будет показано, как отредактировать объектно-реляционную модель.

Пройди тесты
Лучший чат для C# программистов