Создание базы данных с помощью Code First

Это видео и пошаговое руководство содержат общие сведения о разработке Code First, предназначенной для новой базы данных. Этот сценарий включает в себя нацеливание на базу данных, которая не существует, и Code First создаст или пустую базу данных, в которую Code First добавит новые таблицы. Code First позволяет определить модель с помощью C# или VB.Net классов. При необходимости можно выполнить дополнительную настройку с помощью атрибутов для классов и свойств или с помощью свободного API.

Просмотреть видео

Это видео содержит общие сведения о разработке Code First, предназначенной для новой базы данных. Этот сценарий включает в себя нацеливание на базу данных, которая не существует, и Code First создаст или пустую базу данных, в которую Code First добавит новые таблицы. Code First позволяет определить модель с помощью C# или VB.Net классов. При необходимости можно выполнить дополнительную настройку с помощью атрибутов для классов и свойств или с помощью свободного API.

Представляет: Роуэн Миллер (Rowan Miller)

Видео: WMV | MP4 | WMV (ZIP)

Предварительные требования

Для выполнения этого пошагового руководства необходимо установить по крайней мере Visual Studio 2010 или Visual Studio 2012.

Если вы используете Visual Studio 2010, необходимо также установить NuGet .

1. Создание приложения

Чтобы упростить работу, мы создадим базовое консольное приложение, использующее Code First для доступа к данным.

  • Открытие Visual Studio
  • Файл —> создать проект> ...
  • Выберите Windows в меню слева и консольное приложение
  • Введите codeFirstNewDatabaseSample в качестве имени
  • Нажмите кнопку ОК

2. Создание модели

Давайте определим очень простую модель с помощью классов. Мы просто определяем их в файле Program.cs, но в реальном приложении вы разделите классы на отдельные файлы и, возможно, отдельный проект.

Под определением класса Program в Program.cs добавьте следующие два класса.

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }

    public virtual List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

Вы заметите, что мы делаем два свойства навигации (Blog.Posts и Post.Blog) виртуальными. Это позволяет использовать функцию отложенной загрузки Entity Framework. Отложенная загрузка означает, что содержимое этих свойств автоматически загружается из базы данных при попытке доступа к ним.

3. Создание контекста

Теперь пришло время определить производный контекст, представляющий сеанс с базой данных, что позволяет запрашивать и сохранять данные. Мы определяем контекст, производный от System.Data.Entity.DbContext и предоставляющий типизированный dbSet<TEntity> для каждого класса в нашей модели.

Теперь мы начинаем использовать типы из Entity Framework, поэтому необходимо добавить пакет NuGet EntityFramework.

  • Проект —> управление пакетами NuGet... Примечание. Если у вас нет параметра "Управление пакетами NuGet...", установите последнюю версию NuGet.
  • Выберите вкладку "В сети"
  • Выбор пакета EntityFramework
  • Щелкните Установить.

Добавьте оператор using для System.Data.Entity в начало Файла Program.cs.

using System.Data.Entity;

Под классом Post в Program.cs добавьте следующий производный контекст.

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

Ниже приведен полный список содержимого Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace CodeFirstNewDatabaseSample
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }

        public virtual List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public virtual Blog Blog { get; set; }
    }

    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }
}

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

4. Чтение & данных записи

Реализуйте метод Main в Файле Program.cs, как показано ниже. Этот код создает новый экземпляр контекста, а затем использует его для вставки нового блога. Затем он использует запрос LINQ для получения всех блогов из базы данных в алфавитном порядке по названию.

class Program
{
    static void Main(string[] args)
    {
        using (var db = new BloggingContext())
        {
            // Create and save a new Blog
            Console.Write("Enter a name for a new Blog: ");
            var name = Console.ReadLine();

            var blog = new Blog { Name = name };
            db.Blogs.Add(blog);
            db.SaveChanges();

            // Display all Blogs from the database
            var query = from b in db.Blogs
                        orderby b.Name
                        select b;

            Console.WriteLine("All blogs in the database:");
            foreach (var item in query)
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

Теперь вы можете запустить приложение и протестировать его.

Enter a name for a new Blog: ADO.NET Blog
All blogs in the database:
ADO.NET Blog
Press any key to exit...

Где мои данные?

По соглашению DbContext создала базу данных для вас.

  • Если локальный экземпляр SQL Express доступен (установлен по умолчанию в Visual Studio 2010), Code First создал базу данных на этом экземпляре.
  • Если SQL Express недоступен, Code First попытается использовать LocalDB (устанавливается по умолчанию с Visual Studio 2012)
  • База данных называется в честь полного имени производного контекста, в нашем случае это CodeFirstNewDatabaseSample.BloggingContext.

Это только соглашения по умолчанию, и существуют различные способы изменения базы данных, которые code First использует, дополнительные сведения доступны в разделе "Как DbContext обнаруживает модель и подключение к базе данных ". Вы можете подключиться к этой базе данных с помощью обозревателя серверов в Visual Studio

  • Представление —> обозреватель серверов

  • Щелкните правой кнопкой мыши подключения к данным и выберите "Добавить подключение".

  • Если вы еще не подключились к базе данных из обозревателя серверов, перед тем как выбрать Microsoft SQL Server в качестве источника данных

    Выбор источника данных

  • Подключение к LocalDB или SQL Express в зависимости от установленного экземпляра

Теперь можно проверить схему, созданную code First.

Инициал схемы

DbContext разработал классы для включения в модель, просмотрев свойства DbSet, которые мы определили. Затем он использует набор соглашений Code First по умолчанию для определения имен таблиц и столбцов, определения типов данных, поиска первичных ключей и т. д. Далее в этом пошаговом руководстве мы рассмотрим, как можно переопределить эти соглашения.

5. Работа с изменениями модели

Теперь пришло время внести некоторые изменения в модель, когда мы внося эти изменения также необходимо обновить схему базы данных. Для этого мы будем использовать функцию с именем Code First Migrations или миграции.

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

Первым шагом является включение Code First Migrations для нашего BloggingContext.

  • Средства —> диспетчер пакетов библиотеки —> консоль диспетчера пакетов

  • Запустите команду Enable-Migrations в консоли диспетчера пакетов.

  • В наш проект добавлена новая папка Migrations, содержащая два элемента:

    • Configuration.cs — этот файл содержит параметры, которые будут использоваться для миграции BloggingContext. Для этого пошагового руководства нам не нужно ничего менять, но здесь можно указать начальные данные, зарегистрировать поставщиков для других баз данных, изменить пространство имен, в котором создаются миграции и т. д.
    • <timestamp>_InitialCreate.cs — это первая миграция, она представляет изменения, которые уже были применены к базе данных, чтобы взять ее из пустой базы данных в ту, которая включает таблицы "Блоги" и "Записи". Хотя мы позволяем Code First автоматически создавать эти таблицы для нас, теперь, когда мы выбрали миграцию, они были преобразованы в миграцию. Code First также записал в локальной базе данных, что эта миграция уже применена. Метка времени в имени файла используется для упорядочения.

    Теперь давайте внесите изменения в нашу модель, добавьте свойство URL-адреса в класс Blog:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }

    public virtual List<Post> Posts { get; set; }
}
  • Выполните команду Add-Migration AddUrl в консоли диспетчера пакетов. Команда Add-Migration проверяет наличие изменений с момента последней миграции и создает шаблон новой миграции с обнаруженными изменениями. Мы можем присвоить миграции имя; в этом случае мы вызываем миграцию AddUrl. В шаблонном коде говорится, что нам нужно добавить столбец URL-адреса, который может содержать строковые данные в dbo. Таблица блогов. При необходимости можно изменить шаблонный код, но в этом случае это не требуется.
namespace CodeFirstNewDatabaseSample.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddUrl : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Blogs", "Url", c => c.String());
        }

        public override void Down()
        {
            DropColumn("dbo.Blogs", "Url");
        }
    }
}
  • Выполните команду Update-Database в консоли диспетчера пакетов. Эта команда будет применять все ожидающие миграции к базе данных. Миграция InitialCreate уже применена, поэтому миграции просто применят новую миграцию AddUrl. Совет. Вы можете использовать параметр –Verbose при вызове Update-Database для просмотра SQL, выполняемого в базе данных.

Новый столбец URL-адреса теперь добавляется в таблицу "Блоги" в базе данных:

Схема с URL-адресом

6. Заметки к данным

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

  • Давайте добавим класс User в нашу модель
public class User
{
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • Нам также нужно добавить набор в наш производный контекст.
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }
}
  • Если мы попытались добавить миграцию, мы получим ошибку с сообщением "EntityType "User" не определен ключ. Определите ключ для этого EntityType". Так как EF не может знать, что имя пользователя должно быть первичным ключом для пользователя.
  • Теперь мы будем использовать заметки к данным, поэтому необходимо добавить инструкцию using в начало Файла Program.cs.
using System.ComponentModel.DataAnnotations;
  • Теперь заметите свойство Username, чтобы определить, что это первичный ключ.
public class User
{
    [Key]
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • Использование команды Add-Migration AddUser для формирования шаблонов миграции для применения этих изменений к базе данных
  • Выполните команду Update-Database , чтобы применить новую миграцию к базе данных.

Новая таблица теперь добавляется в базу данных:

Схема с пользователями

Полный список заметок, поддерживаемых EF:

7. API Fluent

В предыдущем разделе мы рассмотрели использование заметок к данным для дополнения или переопределения того, что было обнаружено соглашением. Другой способ настройки модели — с помощью API Code First fluent.

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

Чтобы получить доступ к свободному API, переопределите метод OnModelCreating в DbContext. Предположим, что мы хотели переименовать столбец, в который хранится User.DisplayName, в display_name.

  • Переопределите метод OnModelCreating в BloggingContext следующим кодом:
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .Property(u => u.DisplayName)
            .HasColumnName("display_name");
    }
}
  • Используйте команду Add-Migration ChangeDisplayName , чтобы создать шаблон миграции, чтобы применить эти изменения к базе данных.
  • Выполните команду Update-Database , чтобы применить новую миграцию к базе данных.

Теперь столбец DisplayName переименован в display_name:

Схема с переименованным отображаемым именем

Сводка

В этом пошаговом руководстве мы рассмотрели разработку Code First с помощью новой базы данных. Мы определили модель с помощью классов, а затем использовали ее для создания базы данных и хранения и извлечения данных. После создания базы данных мы использовали Code First Migrations для изменения схемы по мере развития модели. Мы также узнали, как настроить модель с помощью заметок к данным и API Fluent.