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

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

Читать бесплатно Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен. Жанр: Программирование год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:
свойства на столбец:

// Car.cs

public class Car : BaseEntity

{

  ...

  public bool IsDrivable { get; set; }

}

// ApplicationDbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)

{

  modelBuilder.Entity<Car>(entity =>

  {

  ...

  entity.Property(e => e.IsDrivable).HasDefaultValue(true);

});

В случае если вы сохраните новую запись с IsDrivable = false, то значение false  игнорируется (т.к. оно является стандартным значением для булевского типа) и будет применяться стандартное значение. Таким образом, значение для IsDrivable всегда будет равно true! Одно из решений предусматривает превращение вашего открытого свойства (и, следовательно, столбца) в допускающее null, но это может не соответствовать бизнес-потребностям.

Другое решение предлагается инфраструктурой EF Core, в частности, ее работой с поддерживающими полями. Вспомните, что если поддерживающее поле существует (и идентифицируется как таковое для свойства через соглашение, аннотацию данных или Fluent API), тогда для действий по чтению и записи EF Core будет использовать поддерживающее поле, а не открытое свойство.

Если вы модифицируете IsDrivable с целью применения поддерживающего поля, допускающего null (но оставите свойство не допускающим null), то EF Core будет выполнять чтение и запись, используя поддерживающее поле, а не свойство. Стандартным значением для булевского типа, допускающего null, является null — не false. Описанное изменение обеспечит ожидаемое поведение свойства:

public class Car

{

  ...

  private bool? _isDrivable;

  public bool IsDrivable

  {

    get => _isDrivable ?? true;

    set => _isDrivable = value;

  }

Для информирования EF Core о поддерживающем поле используется Fluent API:

modelBuilder.Entity<Car>(entity =>

{

  entity.Property(p => p.IsDrivable)

    .HasField("_isDrivable")

    .HasDefaultValue(true);

});

На заметку! В приведенном примере вызов метода HasField() не обязателен, потому что имя поддерживающего поля следует соглашениям об именовании. Он включен в целях демонстрации применения Fluent API для указания поддерживающего поля.

Исполняющая среда EF Core транслирует поле в показанное ниже определение SQL:

CREATE TABLE [dbo].[Inventory](

...

  [IsDrivable] [BIT] NOT NULL,

...

GO

ALTER TABLE [dbo].[Inventory] ADD  DEFAULT (CONVERT([BIT],(1)))

FOR [IsDrivable]

GO

Вычисляемые столбцы

Столбцы также могут вычисляться на основе возможностей хранилища данных. Для SQL Server есть два варианта: вычислять значение, основываясь на других полях в той же самой записи, либо использовать скалярную функцию. Скажем, чтобы создать в таблице Inventory вычисляемый столбец, который объединяет значения PetName и Color для создания DisplayName, применяйте функцию HasComputedColumnSql():

modelBuilder.Entity<Car>(entity =>

{

  entity.Property(p => p.FullName)

    .HasComputedColumnSql("[PetName] + ' (' + [Color] + ')'");

});

В версии EF Core 5 появилась возможность сохранения вычисляемых значений, так что значение вычисляется только при создании или обновлении строки. Хотя в SQL Server упомянутая возможность поддерживается, она присутствует не во всех хранилищах данных, поэтому проверяйте документацию по своему поставщику баз данных:

modelBuilder.Entity<Car>(entity =>

{

  entity.Property(p => p.FullName)

    .HasComputedColumnSql("[PetName] + ' (' + [Color] + ')'", stored:true);

});

Отношения "один ко многим"

Чтобы определить отношение "один ко многим" с помощью Fluent API, выберите одну из сущностей, подлежащих обновлению. Обе стороны навигационной цепочки устанавливаются в одном блоке кода:

modelBuilder.Entity<Car>(entity =>

{

  ...

  entity.HasOne(d => d.MakeNavigation)

    .WithMany(p => p.Cars)

    .HasForeignKey(d => d.MakeId)

    .OnDelete(DeleteBehavior.ClientSetNull)

    .HasConstraintName("FK_Inventory_Makes_MakeId");

});

Если вы выберете в качестве основы для конфигурации навигационной сущности главную сущность, тогда код будет выглядеть примерно так:

modelBuilder.Entity<Make>(entity =>

{

  ...

  entity.HasMany(e=>e.Cars)

    .WithOne(c=>c.MakeNavigation)

    .HasForeignKey(c=>c.MakeId)

    .OnDelete(DeleteBehavior.ClientSetNull)

    .HasConstraintName("FK_Inventory_Makes_MakeId");

 });

Отношения "один к одному"

Отношения "один к одному" конфигурируются аналогично, но только вместо метода WithMany() интерфейса Fluent API используется метод WithOne(). К зависимой сущности добавляется уникальный индекс. Вот код для отношения между сущностями Car и Radio, где применяется зависимая сущность (Radio):

modelBuilder.Entity<Radio>(entity =>

{

  entity.HasIndex(e => e.CarId, "IX_Radios_CarId")

    .IsUnique();

  entity.HasOne(d => d.CarNavigation)

    .WithOne(p => p.RadioNavigation)

    .HasForeignKey<Radio>(d => d.CarId);

});

Даже если отношение определено в главной сущности, то к зависимой сущности все равно добавляется уникальный индекс. Далее приведен код установки отношения между сущностями Car и Radio, где для отношения используется главная сущность:

modelBuilder.Entity<Radio>(entity =>

{

  entity.HasIndex(e => e.CarId, "IX_Radios_CarId")

    .IsUnique();

});

modelBuilder.Entity<Car>(entity =>

{

  entity.HasOne(d => d.RadioNavigation)

    .WithOne(p => p.CarNavigation)

    .HasForeignKey<Radio>(d => d.CarId);

});

Отношения "многие ко многим"

Отношения "многие ко многим" гораздо легче настраивать посредством Fluent API. Имена полей внешних ключей, имена индексов и каскадное поведение могут быть установлены в операторах, определяющих отношение. Ниже показан пример отношения "многие ко многим", переделанный с применением Fluent API (имена ключей и столбцов были изменены, чтобы улучшить читабельность):

modelBuilder.Entity<Car>()

  .HasMany(p => p.Drivers)

  .WithMany(p => p.Cars)

  .UsingEntity<Dictionary<string, object>>(

    "CarDriver",

    j => j

  .HasOne<Driver>()

      .WithMany()

      .HasForeignKey("DriverId")

      .HasConstraintName("FK_CarDriver_Drivers_DriverId")

      .OnDelete(DeleteBehavior.Cascade),

    j => j

      .HasOne<Car>()

      .WithMany()

      .HasForeignKey("CarId")

      .HasConstraintName("FK_CarDriver_Cars_CarId")

      .OnDelete(DeleteBehavior.ClientCascade));

Соглашения, аннотации данных и Fluent API — что выбрать?

В настоящий момент вас может интересовать, какой из вариантов следует выбирать для формирования ваших сущностей, а также их связей друг с другом и с хранилищем данных? Ответ: все три. Соглашения активны всегда (если только вы не переопределите их посредством аннотаций данных или Fluent API). С помощью аннотаций данных можно делать почти все то, на что способны методы Fluent API, и хранить информацию в самом сущностном классе, повышая в ряде случаев читабельность кода и удобство его сопровождения. Из трех вариантов

Перейти на страницу:

Эндрю Троелсен читать все книги автора по порядку

Эндрю Троелсен - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


Язык программирования C#9 и платформа .NET5 отзывы

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


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*