Object Relation Designer

60

»» В ДАННОЙ СТАТЬЕ ИСПОЛЬЗУЕТСЯ ИСХОДНЫЙ КОД ДЛЯ ПРИМЕРОВ

В дополнение к утилите SQLMetal существует также графический инструмент пользователя для генерации сущностных классов, который работает в среде Visual Studio. Этот инструмент называется Object Relational Designer, и на него часто ссылаются, как на LINQ to SQL Designer, O/R Designer или даже DLinq Designer.

Визуальный конструктор Object Relational Designer — более избирательный инструмент, чем SQLMetal. Визуальный конструктор предоставляет в распоряжение разработчика средства моделирования сущностных классов методом перетаскивания. При этом беспокоиться не нужно: визуальный конструктор сделает большую часть рутинной работы. Ваше дело — выбрать таблицы базы данных, которые хотите моделировать, если они доступны, и отредактировать имена сущностных классов и их свойств. Конечно, если необходим полный контроль, то в визуальном конструкторе можно выполнить все моделирование вручную.

Создание файла классов LINQ to SQL

Первый шаг в использовании визуального конструктора — создание файла классов LINQ to SQL посредством щелчка правой кнопкой мыши на проекте и выбора в контекстном меню пункта Add => New Item (Добавить --> Новый элемент).

Откроется диалоговое окно Add New Item (Добавить новый элемент). Выберите в списке установленных шаблонов LINQ to SQL Classes (Классы LINQ to SQL). Измените имя по своему усмотрению. Имя моделируемой базы данных — обычно подходящий выбор для имени файла классов LINQ to SQL. Расширение файла классов LINQ to SQL выглядит как .dbml. В рассматриваемом примере в качестве имени файла используется Northwind.dbml:

Новый шаблон LINQ to SQL

Указав имя для файла, щелкните на кнопке Add (Добавить). После этого появится пустое окно. Это — поверхность проектирования визуального конструктора.

Щелкнув на этой поверхности и заглянув в окно Properties (Свойства), вы увидите там свойство по имени Name. Значением свойства Name будет имя сгенерированного класса-наследника DataContext. Поскольку файл классов LINQ to SQL назван Northwind.dbml, по умолчанию значением свойства Name будет NorthwindDataContext, что вполне подходит.

В окне Solution Explorer (Проводник решения) непосредственно под файлом Northwind.dbml есть еще один файл по имени Northwind.designer.cs. Открыв его, вы увидите, что пока он содержит очень мало кода. По сути, он будет содержать конструкторы для нового класса-наследника DataContext, который называется NorthwindDataContext.

Добавление сущностного класса

Найдите базу данных Northwind в списке Data Connections в окне Server Explorer. Разверните узел Tables (Таблицы) и вы увидите список таблиц базы данных Northwind. Сущностные классы создаются перетаскиванием таблиц из списка Tables в окне Server Explorer на поверхность проектирования:

Таблицы базы данных Northwind

Перетащите таблицу Customers из окна Server Explorer на поверхность проектирования. Тем самым вы указываете визуальному конструктору создать сущностный класс для таблицы Customers по имени Customer. После этого поверхность проектирования должна выглядеть, как показано на рисунке:

Добавление таблицы в DBML-файл

Может понадобиться изменить размеры некоторых панелей, чтобы ясно все видеть. За счет перетаскивания таблицы Customers на поверхность проектирования визуального конструктора добавляется исходный код сущностного класса Customer в файл Northwind.designer.cs. После построения проекта можно приступать к использованию сущностного класса Customer для доступа и обновления данных в базе Northwind. Вот как все просто!

Однако прежде чем строить проект и писать код, использующий сгенерированные сущностные классы, следует создать еще несколько дополнительных вещей, необходимых для использования всех преимуществ LINQ to SQL. Теперь перетащите на поверхность проектирования таблицу Orders из окна Server Explorer. Подходящим образом расположите ее на поверхности. Это указывает визуальному конструктору на необходимость создания сущностного класса для таблицы Orders по имени Order. После этого поверхность визуального конструктора будет выглядеть, как показано на рисунке:

Добавление еще одной таблицы

На поверхность проектирования видна пунктирная линия, соединяющая класс Customer с классом Order. Эта пунктирная линия представляет отношение, которое в LINQ to SQL называется ассоциацией, между таблицами Customers и Orders, заданное ограничением внешнего ключа FK_Orders_Customers и существующее в базе данных Northwind. Эта линия указывает на то, что визуальный конструктор также создаст необходимую ассоциацию в сущностных классах для поддержки отношений между этими двумя сущностными классами. Наличие такой ассоциации позволит получать ссылку на коллекцию заказов определенного заказчика через некоторое свойство объекта Customer, а также получать ссылку на заказчика, разместившего конкретный заказ, через соответствующее свойство объекта Order.

Если сгенерированная ассоциация не нужна, выберите пунктирную линию, представляющую ее, и удалите нажатием <Delete>, или щелкните правой кнопкой мыши и выберите в контекстном меню пункт Delete (Удалить).

Использование сгенерированных визуальным конструктором сущностных классов

Теперь все готово к использованию сущностных классов, сгенерированных визуальным конструктором. Ниже приведен пример запроса базы данных для получения списка заказчиков из Лондона:

NorthwindDataContext db = new NorthwindDataContext();

            IQueryable<Customer> custs = from c in db.Customers
                                         where c.City == "London"
                                         select c;

            foreach (Customer c in custs)
            {
                Console.WriteLine("{0} имеет {1} заказов.", c.CompanyName, c.Orders.Count);
            }

Это похоже на другой пример с исключением. Обратите внимание, что при создании экземпляра объекта NorthwindDataContext не было указано никакой информации о соединении. Дело в том, что визуальный конструктор сгенерировал класс NorthwindDataContext с конструктором без параметров, который получает информацию соединения из файла настроек проекта по имени app.config. Он даже установил соответствующее значение в файле настроек.

В предыдущем коде обратите внимание на возможность доступа к заказам полученного заказчика через свойство Orders объекта Customer. Это позволяет делать ассоциация, автоматически созданная визуальным конструктором. Здорово, не правда ли? А вот результат работы кода:

Пример использования сгенерированных визуальным конструктором сущностных классов

Редактирование модели сущностных классов

Естественно, может понадобится управлять именами сущностных классов, их свойствами (настройками сущностных классов), именами этих свойств (членов сущностных классов) и свойствами (членами сущностных классов) свойств (настройками). Система именования, предложенная Microsoft, достаточно запутана. Действительно ли была необходимость называть члены классов свойствами, зная, что в Visual Studio свойствами обозначаются настройки?

Гибкость и простота использования для управления именами и свойствами сущностный классов это то, что делает визуальный конструктор столь привлекательным. Здесь практически все можно делать с помощью щелчков и перетаскивания:

Редактирование имени сущностного класса

Чтобы отредактировать имя сущностного класса, дважды щелкните на его имени либо выберите сущностный класс на поверхности проектирования и модифицируйте свойство Name в окне Properties (Свойства).

Редактирование свойств сущностного класса (настроек сущностного класса)

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

Редактирование имени свойства сущностного класса (члена сущностного класса)

Можно редактировать имя свойства сущностного класса как члена сущностного класса, выполнив тройной щелчок на имени свойства. Пусть не удивляет такая экзотическая вещь, как тройной щелчок — она существует и действует. Или же можно выбрать свойство сущностного класса на поверхности и отредактировать его свойство Name в окне Properties.

Редактирование свойств свойства сущностного класса (настройки)

Можно редактировать свойства свойств сущностного класса, выбрав свойство на поверхности проектирования и модифицировав соответствующее свойство в окне Properties. В этом окне вы найдете все свойства, соответствующие свойствам атрибутов сущностного класса, такие как Name и UpdateCheck, для атрибута Column сущностного класса.

Добавление объектов к модели сущностных классов

Перетащить сущностный класс на поверхность достаточно просто — до тех пор, пока есть соответствующая таблица базы данных в Server Explorer. Но бывают случаи, когда вы лишены такого удобства. Возможно, вы определили сущностный класс сначала, и планируете генерировать базу данных, вызвав метод CreateDatabase на объекте DataContext. Или, может быть, вы собираетесь воспользоваться преимуществом наследования сущностного класса, и нет соответствующей таблицы для отображения.

Добавление нового сущностного класса

Один из способов добавления новых классов к модели сущностных классов заключается в перетаскивании таблиц базы данных из окна Server Explorer, как это делалось в предыдущем разделе. Другой способ создания сущностного класса состоит в перетаскивании на поверхность проектирования объекта Object Relational Designer Class из панели инструментов Visual Studio. Отредактируйте имя и установите свойства сущностного класса, как было описано в предыдущем разделе.

Добавление новых свойств (членов) сущностного класса

Для добавления новых свойств (членов) сущностного класса необходимо выполнить щелчок правой кнопкой мыши на сущностном классе в визуальном конструкторе и выбрать в контекстном меню пункт Add --> Properties (Добавить --> Свойства). Как только свойство добавлено к сущностному классу, следуйте инструкциям по редактированию свойств свойства сущностного класса, приведенным в разделе "Редактирование свойств свойства сущностного класса (настройки)".

Добавление новой ассоциации

Вместо использования механизма перетаскивания для создания ассоциации, как вы поступали при добавлении нового сущностного класса из панели инструментов Visual Studio, ассоциация создается щелчком на объекте Association (Ассоциация) в панели инструментов, за которым следует щелчок на сущностном классе, задающем сторону один в отношении "один ко многим", а за ним — щелчок на дочернем сущностном классе, задающем сторону многие в том же отношении.

Каждый из этих классов должен иметь соответствующее свойство перед тем, как вы добавите ассоциацию, чтобы можно было отобразить первичный ключ на стороне один на внешний ключ на стороне многие. Выбор второго класса (стороны многие) ассоциации приводит к открытию диалогового окна Association Editor (Редактор ассоциации), которое позволяет отобразить свойство первого класса на соответствующее свойство второго класса.

Надлежащим образом отобразив свойства и закрыв окно Association Editor, вы увидите пунктирную линию, соединяющую родительский и дочерний сущностные классы.

Выберите ассоциацию щелчком на пунктирной линии и установите соответствующие свойства в окне Properties.

Добавление нового наследования

Object Relational Designer можно также использовать для моделирования отношения наследования. Добавление отношения наследования подобно добавлению новой ассоциации. Выберите объект Inheritance (Наследование) в панели инструментов Visual Studio Toolbox и щелкните на сущностном классе, который будет наследником, а затем — на сущностном классе, который будет базовым. Удостоверьтесь, что установлены все соответствующие свойства сущностного класса, как определено атрибутами InheritanceMapping и Column сущностного класса.

Добавление хранимых процедур и функций, определяемых пользователем

Чтобы заставить визуальный конструктор сгенерировать код, необходимый для вызова хранимых процедур и функций, определяемых пользователем, перетащите хранимую процедуру или пользовательскую функцию из Server Explorer в панель Methods (Методы) визуального конструктора.

Переопределение методов вставки, обновления и удаления

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

Однако переопределение методов вставки, обновления и удаления также легко выполняется в визуальном конструкторе. Предположим, что есть хранимая процедуры по имени InsertCustomer, которая будет вставлять запись о новом заказчике в таблицу Customers базы данных Northwind. Ниже показана хранимая процедура, которая для этого используется:

ALTER PROCEDURE dbo.InsertCustomer
  (
  @CustomerID         nchar(5),
  @CompanyName        nvarchar(40),
  @ContactName        nvarchar(30),
  @ContactTitle       nvarchar(30),
  @Address            nvarchar(60),
  @City               nvarchar(15),
  @Region             nvarchar(15),
  @PostalCode         nvarchar(10),
  @Country            nvarchar(15),
  @Phone              nvarchar(24),
  @Fax                nvarchar(24)
  )
AS
  INSERT INTO Customers
  (
    CustomerID,
    CompanyName,
    ContactName,
    ContactTitle,
    Address,
    City,
    Region,
    PostalCode,
    Country,
    Phone,
    Fax
  )
  VALUES
  (
    @CustomerID,
    @CompanyName,
    @ContactName,
    @ContactTitle,
    @Address,
    @City,
    @Region,
    @PostalCode,
    @Country,
    @Phone,
    @Fax
  )

Чтобы переопределить метод вставки сущностного класса Customer, сначала убедитесь, что панель Methods видима. Если нет, щелкните правой кнопкой мыши в панели визуального конструктора и выберите в контекстном меню пункт Show Methods Panel (Показать панель методов). Затем откройте окно Server Explorer в Visual Studio, если оно еще не открыто. Найдите и разверните узел Stored Procedures (Хранимые процедуры) в узле соответствующей базы данных. Окно Visual Studio должно выглядеть подобно показанному на рисунке:

Нахождение хранимой процедуры

Найдя хранимую процедуру, перетащите ее в панель Methods, которая представляет собой окно справа от модели сущностных классов.

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

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

Теперь, когда хранимая процедура InsertCustomer находится в панели Methods, выберите класс Customer на поверхности проектирования и просмотрите окно свойств Properties. Теперь вы увидите список Default Methods (Методы по умолчанию). Выберите метод Insert, щелкнув на нем. Вы получите кнопку выбора с многоточием (...), как показано на рисунке:

Выбор метода Insert

Теперь щелкните на кнопке с многоточием для открытия диалогового окна Configure Behavior (Настройка поведения). Выберите переключатель Customize (Настроить) и в раскрывающемся списке выберите хранимую процедуру InsertCustomer. Отобразите аргументы метода в списке Method Arguments слева на соответствующие свойства пользовательского класса в списке Class Properties справа:

Отображение аргументов метода на свойства класса

Теперь все аргументы метода отображены по умолчанию на соответствующие свойства класса.

После отображения всех аргументов метода щелкните на кнопке ОК. После этого вы готовы к вставке записей Customer посредством вызова хранимой процедуры InsertCustomer. В примере ниже новый заказчик создается с использованием хранимой процедуры InsertCustomer:

NorthwindDataContext db = new NorthwindDataContext();

            db.Log = Console.Out;

            Customer cust =
              new Customer
              {
                  CustomerID = "EWICH",
                  CompanyName = "Every 'Wich Way",
                  ContactName = "Vickey Rattz",
                  ContactTitle = "Owner",
                  Address = "105 Chip Morrow Dr.",
                  City = "Alligator Point",
                  Region = "FL",
                  PostalCode = "32346",
                  Country = "USA",
                  Phone = "(800) EAT-WICH",
                  Fax = "(800) FAX-WICH"
              };

            db.Customers.InsertOnSubmit(cust);

            db.SubmitChanges();

            Customer customer = db.Customers.Where(c => c.CustomerID == "EWICH").First();
            Console.WriteLine("{0} - {1}", customer.CompanyName, customer.ContactName);

            // Восстановление базы данных
            db.Customers.DeleteOnSubmit(cust);
            db.SubmitChanges();

Обратите внимание, что никакое пространство имен для класса Customer не указывается, т.е. используется класс Customer, находящийся в пространстве имен проекта — сгенерированный визуальным конструктором класс Customer.

В приведенном примере нет ничего особенного. Здесь просто создается экземпляр DataContext, которым в данном случае является сгенерированный визуальным конструктором NorthwindDataContext. Затем создается новый объект Customer, который вставляется в свойство Customers типа Table <Т>. После этого вызывается метод SubmitChanges для сохранения нового заказчика в базе данных. Далее этот заказчик запрашивается из базы данных и отображается на консоли — просто чтобы доказать, что запись действительно была вставлена в таблицу базы. И последнее, что делается в коде — только что вставленный заказчик удаляется вызовом метода DeleteOnSubmit с фиксацией изменений в базе данных с помощью метода SubmitChanges. Это позволяет оставить базу данных в изначальном состоянии. Последующие примеры будут работать правильно, а этот пример может быть выполнен многократно. Рассмотрим вывод программы:

Создание записи Customer с переопределенным методом вставки по умолчанию
Пройди тесты
Лучший чат для C# программистов