Книги онлайн и без регистрации » Разная литература » Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 286 287 288 289 290 291 292 293 294 ... 407
Перейти на страницу:
и Tracked класса ChangeTracker:

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)

  : base(options)

{

  ...

  ChangeTracker.Tracked += ChangeTracker_Tracked;

  ChangeTracker.StateChanged += ChangeTracker_StateChanged;

}

Аргументы события Tracked содержат ссылку на сущность, которая инициировала событие, и указывают, было оно получено из запроса (загруженного из базы данных) или добавлено программно. Добавьте в класс ApplicationDbContext следующий обработчик событий:

private void ChangeTracker_Tracked(object? sender, EntityTrackedEventArgs e)

{

  var source = (e.FromQuery) ? "Database" : "Code";

  if (e.Entry.Entity is Car c)

  {

    Console.WriteLine($"Car entry {c.PetName} was added from {source}");

  }

}

Событие StateChanged инициируется при изменении состояния сущности. Одно из применений этого события — аудит. Поместите в класс ApplicationDbContext приведенный ниже обработчик событий. Если свойство NewState сущности имеет значение Unchanged, тогда выполняется проверка свойства OldState для выяснения, сущность была добавлена или же модифицирована.

private void ChangeTracker_StateChanged(object? sender,

                                        EntityStateChangedEventArgs e)

{

  if (e.Entry.Entity is not Car c)

  {

    return;

  }

  var action = string.Empty;

   Console.WriteLine($"Car {c.PetName}

           was {e.OldState} before the state changed to {e.NewState}");

  switch (e.NewState)

  {

    case EntityState.Unchanged:

      action = e.OldState switch

      {

        EntityState.Added => "Added",

        EntityState.Modified => "Edited",

        _ => action

      };

      Console.WriteLine($"The object was {action}");

      break;

  }

}

Создание миграции и обновление базы данных

На этой стадии оба проекта компилируются и все готово к созданию еще одной миграции для обновления базы данных. Введите в каталоге проекта AutoLot.Dal следующие команды (каждая команда должна вводиться в одной строке):

dotnet ef migrations add UpdatedEntities -o EfStructuresMigrations

 -c AutoLot.Dal.EfStructures.ApplicationDbContext

dotnet ef database update UpdatedEntities

 -c AutoLot.Dal.EfStructures.ApplicationDbContext

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

 Осталось внести в базу данных два изменения: создать хранимую процедуру GetPetName, рассмотренную в главе 21, и добавить представление базы данных, которое объединяет таблицу Orders с деталями Customer, Car и Make.

Добавление класса MigrationHelpers

Хранимая процедура и представление будут создаваться с использованием миграции, которая требует написания кода вручную. Причина поступать так (вместо того, чтобы просто открыть Azure Data Studio и запустить код T-SQL) — желание поместить полное конфигурирование базы данных в один процесс. Когда все содержится в миграциях, единственный вызов dotnet ef database update гарантирует, что база данных является актуальной, включая конфигурацию EF Core и специальный код SQL.

Выполнение команды the dotnet ef migrations add при отсутствии изменений в модели все равно приводит к созданию файлов миграции, имеющих правильную отметку времени, с пустыми методами Up() и Down(). Введите показанную ниже команду для создания пустой миграции (но не применения миграции):

dotnet ef migrations add SQL -o EfStructuresMigrations

 -c AutoLot.Dal.EfStructures.ApplicationDbContext

Создайте в каталоге EfStructures проекта AutoLot.Dal новый файл по имени MigrationHelpers.cs. Добавьте оператор using для пространства имен Microsoft.EntityFrameworkCore.Migrations, сделайте класс открытым и статическим и поместите в него следующие методы, которые используют MigrationBuilder для запуска операторов SQL в отношении базы данных:

namespace AutoLot.Dal.EfStructures

{

  public static class MigrationHelpers

  {

    public static void CreateSproc(MigrationBuilder migrationBuilder)

    {

      migrationBuilder.Sql($@"

          exec (N'

          CREATE PROCEDURE [dbo].[GetPetName]

              @carID int,

              @petName nvarchar(50) output

          AS

          SELECT @petName = PetName from dbo.Inventory where Id = @carID

      ')");

    }

    public static void DropSproc(MigrationBuilder migrationBuilder)

    {

      migrationBuilder.Sql("DROP PROCEDURE [dbo].[GetPetName]");

    }

    public static void CreateCustomerOrderView(

      MigrationBuilder migrationBuilder)

    {

      migrationBuilder.Sql($@"

          exec (N'

          CREATE VIEW [dbo].[CustomerOrderView]

          AS

      SELECT dbo.Customers.FirstName, dbo.Customers.LastName,

             dbo.Inventory.Color, dbo.Inventory.PetName,

             dbo.Inventory.IsDrivable,

             dbo.Makes.Name AS Make

          FROM dbo.Orders

          INNER JOIN dbo.Customers ON dbo.Orders.CustomerId = dbo.Customers.Id

          INNER JOIN dbo.Inventory ON dbo.Orders.CarId = dbo.Inventory.Id

          INNER JOIN dbo.Makes ON dbo.Makes.Id = dbo.Inventory.MakeId

      ')");

    }

    public static void DropCustomerOrderView(MigrationBuilder migrationBuilder)

    {

      migrationBuilder.Sql("EXEC (N' DROP VIEW [dbo].[CustomerOrderView] ')");

    }

  }

}

Обновление и применение миграции

Для каждого объекта SQL Server в классе MigrationHelpers имеется два метода: один создает объект, другой удаляет объект. Вспомните, что при применении миграции выполняется метод Up(), а при откате миграции — метод Down(). Вызовы статических методов создания должны попасть в метод Up() миграции, тогда как вызовы статических методов удаления — в метод Down() миграции. В результате применения миграции создаются два объекта SQL Server, которые в случае отката миграции благополучно удаляются. Ниже приведен модифицированный код миграции:

namespace AutoLot.Dal.EfStructures.Migrations

{

  public partial class SQL : Migration

  {

    protected override void Up(MigrationBuilder migrationBuilder)

    {

      MigrationHelpers.CreateSproc(migrationBuilder);

      MigrationHelpers.CreateCustomerOrderView(migrationBuilder);

    }

    protected override void Down(MigrationBuilder migrationBuilder)

    {

      MigrationHelpers.DropSproc(migrationBuilder);

      MigrationHelpers.DropCustomerOrderView(migrationBuilder);

    }

  }

}

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

dotnet ef database update -c AutoLot.Dal.EfStructures.ApplicationDbContext

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

protected override void Up(MigrationBuilder migrationBuilder)

{

// MigrationHelpers.CreateSproc(migrationBuilder);

  MigrationHelpers.CreateCustomerOrderView(migrationBuilder);

}

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

1 ... 286 287 288 289 290 291 292 293 294 ... 407
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. В коментария нецензурная лексика и оскорбления ЗАПРЕЩЕНЫ! Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?