Сегодня я попытаюсь разобраться с шаблоном разработки Code First для Entity Framework, а так же что такое миграции и для чего они нужны. Речь пойдет о EF 5.0.
Code First позволяет определить модель данных на основе POCO-классов (Plain Old CLR Objects), а затем сопоставить эти классы с существующей или сгенерировать новую базу данных.
Что же, попробуем начать и будем разбираться по ходу дела. Создадим пустой Console Application. Реализуем простенький пример с сотрудниками. Поэтому создадим для начала класс Employee:
public class Employee { [StringLength(50)] public int Id { get; set; } public string FirstName { get; set; } }Так же добавим класс Department:
public class Department { public int Id { get; set; } [StringLength(50)] public string Name { get; set; } public ICollection <Employee> Employees { get; set; } }
Виды отношений между таблицами будут распознаны, для отношения типа 1:n в классе Department необходимо реализовать интерфейс ICollection<T> - где T является типом объекта в другой таблице связи, в данном случае Employee. Если же нужно отношение тип n:m, тогда необходимо интерфейс ICollection<T> реализовать в обоих классах.
По умолчанию свойство с именем Id или <class name>Id считается первичным ключом (регистр симвоолов при этом не учитывается), так же, начиная с EF 5.0, в качестве первичного ключа может использоваться Guid (в данном примере оставим int). Если же есть необходимость использовать другое имя для первичного ключа, то для это применяется атрибут Key.
Примечание: при использовании Guid в качестве первичного ключа его необходимо инициализировать в конструкторе
В приведенном выше коде я использовал атрибут [StringLength(int)], который задает максимальную длину строки, без использования данного атрибута будет применен тип nvarchar(max). Есть достаточно много атрибутов, которые облегчают жизнь, и которые будут применяться в этом примере, но я не хочу тратить время на их описание. Основные из них можно посмотреть тут.
Продолжаем!
Т.к. у нас пустое приложение, нам необходимо добавить ссылку на EF5 с помощью NuGet Packages, благодаря чему появятся все необходимые библиотеки:
Такого же эффекта можно добиться, используя Package Manager Console (TOOLS > Library Package Manager) совместно с командой Install-Package EntityFramework –Pre
Теперь добавим настройки подключения к БД. Для этого добавим в App.Config параметр <connectionStrings>:
<connectionStrings> <add name="CodeContext" connectionString="Data Source=ServerName; Initial Catalog=EFTest;Integrated Security=true;" providerName="System.Data.SqlClient"/> </connectionStrings>
Далее создадим контекст базы данных, для чего необходимо создать производный от DbContext класс. Создадим файл CodeContext.cs и добавим следующий код:
namespace Employee.EF { public class CodeContext : DbContext { public CodeContext() : base("CodeContext") { } public DbSet<Employee> Employees { get; set; } public DbSet<Department> Departments { get; set; } } }
Обратите внимание! Если имя connectionString совпадает с именем контекста (в данном случае это CodeContext и они совпадают), то DbContext распознает строку подключения к БД и все будет ОК. Если же имена разные, то необходимо для DbContext использовать это подключение путем указания имени подключения в конструкторе DbContext. Вообще, если не указывать настройки подключения, то DbContext использует имя производного класса контекста - Employee.EF.CodeContext, как имя базы данных и создает подключении используя SQL Express или LocalDb (устанволен по умолчанию в VisualStudio 2012). Если же установлены оба из них, то по умолчанию будет использоваться SQL Express.
Итак, давайте перейдем в наш programs.cs и добавим следующий код в класс Program:
static void Main(string[] args) { using (var ctx = new CodeContext()) { ctx.Employees.Add(new Employee {FirstName = "Alex"}); ctx.SaveChanges(); var employees = ctx.Employees.ToList(); foreach (var employee in employees) { Console.WriteLine(employee.FirstName); } Console.ReadKey(); } }
Теперь можно запустить наш код!
Нам вывелось содержимое таблицы Employees, следовательно наша база данных создалась автоматически:
Как видите, связь между таблицами создалась автоматически.
Теперь предлагаю внести некоторые изменения в какой-либо из наших классов, например, Employee:
public class Employee { public int Id { get; set; } [StringLength(50)] [Required] public string FirstName { get; set; } [StringLength(50)] [Required] public string SecondName { get; set; } }
И добавим фамилию нашему сотруднику, т.к. у поля SecondName появился атрибут [Required], т.е. not null.
ctx.Employees.Add(new Employee {FirstName = "Alex", SecondName = "Tarasov"}); ctx.SaveChanges();
и попробуем скомпилировать код, в результате чего получим следующую ошибку:
как видно из сообщения - сейчас самое время подойти к вопросу миграции.
Отступление: Если на этапе разработки вы не работаете с большими объемами данных или эти данные вообще вам не важны, то можно применить следующий подход - добавим класс инициализатор:
class Init: DropCreateDatabaseIfModelChanges<CodeContext> { }
и пропишем инициализатор в program.cs:
Database.SetInitializer<CodeContext>(new Init());
Так может показаться, что все замечательно, если базы нет, то она создастся, если есть - удалится и создастся, НО будет хорошо только в том случае, если у вас нет множества данных в БД, а ведь работу над проектом может вести много разработчиков, что реально может привести к хаотичному пересозданию базы и потери каких-либо данных, пусть даже тестовых.
Короче говоря - МИГРАЦИИ БЫТЬ! Поэтому мы не будем при изменении модели пересоздавать БД.
Итак, миграция - это поддержка версионности базы данных.
Давайте посмотрим, что у нас есть сейчас
На данный момент нас интересует таблица MigrationHistory, в которой содержаться имя версии БД, время ее создания, так называемый слепок модели и версия EF. Эта таблица создается автоматически и не попадает в базу благодаря неведомому волшебству, даже без включенного механизма миграции. При использовании миграции мы можем с уверенностью сказать, что все изменения с базой будут попадать в эту таблицу и мы с можем всегда увидеть, в каком состоянии находится наша БД.
В следующей части этой статьи побробнее разберем пример с миграцией
Полезные ссылки:
Комментариев нет:
Отправить комментарий