Entity Framework
Code First - Fluent API
Поиск…
замечания
Существует два общих способа указания HOW Entity Framework сопоставляет классы POCO с таблицами, столбцами базы данных и т. Д .: аннотации данных и свободный API .
Хотя аннотации данных являются простыми для чтения и понимания, у них отсутствуют определенные функции, такие как указание поведения «Cascade on Delete» для объекта. Fluent API, с другой стороны, немного сложнее в использовании, но обеспечивает гораздо более сложный набор функций.
Модели отображения
EntityFramewok Fluent API - это мощный и элегантный способ сопоставления ваших кодовых моделей домена с базой данных. Это также можно использовать с кодом сначала с существующей базой данных . У вас есть два варианта при использовании Fluent API : вы можете напрямую сопоставлять свои модели с методом OnModelCreating или создавать классы сопоставления, которые наследуются от EntityTypeConfiguration, а затем добавлять эти модели в modelBuilder по методу OnModelCreating . Второй вариант, который я предпочитаю, и я покажу пример этого.
Шаг первый: создайте модель.
public class Employee
{
public int Id { get; set; }
public string Surname { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public short Age { get; set; }
public decimal MonthlySalary { get; set; }
public string FullName
{
get
{
return $"{Surname} {FirstName} {LastName}";
}
}
}
Шаг второй: создать класс сопоставления
public class EmployeeMap
: EntityTypeConfiguration<Employee>
{
public EmployeeMap()
{
// Primary key
this.HasKey(m => m.Id);
this.Property(m => m.Id)
.HasColumnType("int")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// Properties
this.Property(m => m.Surname)
.HasMaxLength(50);
this.Property(m => m.FirstName)
.IsRequired()
.HasMaxLength(50);
this.Property(m => m.LastName)
.HasMaxLength(50);
this.Property(m => m.Age)
.HasColumnType("smallint");
this.Property(m => m.MonthlySalary)
.HasColumnType("number")
.HasPrecision(14, 5);
this.Ignore(m => m.FullName);
// Table & column mappings
this.ToTable("TABLE_NAME", "SCHEMA_NAME");
this.Property(m => m.Id).HasColumnName("ID");
this.Property(m => m.Surname).HasColumnName("SURNAME");
this.Property(m => m.FirstName).HasColumnName("FIRST_NAME");
this.Property(m => m.LastName).HasColumnName("LAST_NAME");
this.Property(m => m.Age).HasColumnName("AGE");
this.Property(m => m.MonthlySalary).HasColumnName("MONTHLY_SALARY");
}
}
Объясним отображения:
- HasKey - определяет первичный ключ. Также можно использовать составные первичные ключи . Например: this.HasKey (m => new {m.DepartmentId, m.PositionId}) .
- Свойство - позволяет нам настраивать свойства модели.
- HasColumnType - указать тип столбца уровня базы данных. Обратите внимание, что это может быть разным для разных баз данных, таких как Oracle и MS SQL.
- HasDatabaseGeneratedOption - указывает, вычисляется ли свойство на уровне базы данных. Числовые ПК имеют значение DatabaseGeneratedOption.Identity по умолчанию, вы должны указать DatabaseGeneratedOption.None, если вы не хотите, чтобы это было так.
- HasMaxLength - ограничивает длину строки.
- IsRequired - маркирует свойство как требуемое.
- HasPrecision - позволяет указать точность для десятичных знаков.
- Игнорировать - Игнорировать свойство полностью и не отображать его в базе данных. Мы проигнорировали FullName, потому что этот столбец не нужен в нашей таблице.
- ToTable - указать имя таблицы и имя схемы (необязательно) для модели.
- HasColumnName - связывает свойство с именем столбца. Это не требуется, если имена свойств и имена столбцов идентичны.
Шаг третий: добавьте класс сопоставления в конфигурации.
Нам нужно сказать EntityFramework, чтобы использовать наш класс mapper. Для этого нам нужно добавить его в modelBuilder.Configurations on OnModelCreating :
public class DbContext()
: base("Name=DbContext")
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new EmployeeMap());
}
}
И это все. Мы все готовы идти.
Основной ключ
Используя метод .HasKey (), свойство может быть явно сконфигурировано как первичный ключ объекта.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>().HasKey(p => p.PersonKey);
}
}
Композитный первичный ключ
Используя метод .HasKey (), набор свойств может быть явно сконфигурирован как составной первичный ключ объекта.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>().HasKey(p => new { p.FirstName, p.LastName });
}
}
Максимальная длина
Используя метод .HasMaxLength (), максимальное количество символов может быть настроено для свойства.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>()
.Property(t => t.Name)
.HasMaxLength(100);
}
}
Полученный столбец с указанной длиной столбца:
Обязательные свойства (NOT NULL)
Используя метод .IsRequired (), свойства могут быть указаны как обязательные, что означает, что столбец будет иметь ограничение NOT NULL.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>()
.Property(t => t.Name)
.IsRequired();
}
}
Полученный столбец с ограничением NOT NULL:
Идентификация внешнего ключа
Когда свойство навигации существует на модели, Entity Framework автоматически создаст столбец внешнего ключа. Если требуется конкретное имя внешнего ключа, но не содержится в качестве свойства в модели, оно может быть установлено явно с использованием Fluent API. Используя метод Map
при установлении отношений с внешним ключом, любое уникальное имя может использоваться для внешних ключей.
public class Company
{
public int Id { get; set; }
}
public class Employee
{
property int Id { get; set; }
property Company Employer { get; set; }
}
public class EmployeeContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasRequired(x => x.Employer)
.WithRequiredDependent()
.Map(m => m.MapKey("EmployerId"));
}
}
После определения отношения метод Map
позволяет явно указать имя внешнего ключа, выполнив MapKey
. В этом примере, что привело бы к имени столбца Employer_Id, теперь является EmployerId.