Entity Framework
コードファースト - 流暢なAPI
サーチ…
備考
HOW Entity FrameworkがPOCOクラスをデータベーステーブル、列などにマップすることを指定する一般的な方法は2つあります。 データ注釈とFluent API 。
データ注釈は読みやすく、理解しやすいものですが、エンティティの「削除時にカスケード」動作を指定するなどの機能はありません。一方、Fluent APIはもう少し複雑ですが、はるかに高度な機能を提供します。
モデルのマッピング
EntityFramewok Fluent APIは、 コードファーストドメインモデルを基になるデータベースにマッピングする、強力かつエレガントな方法です。これは既存のデータベースでコードファーストで使用することもできます 。 Fluent APIを使用する場合は、 OnModelCreatingメソッドでモデルを直接マップするか、 EntityTypeConfigurationから継承したマッパークラスを作成して、 OnModelCreatingメソッドのmodelBuilderにそのモデルを追加することができます。 第二の選択肢は私が好むもので、その例を示すつもりです。
ステップ1:モデルを作成します。
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}";
}
}
}
ステップ2:マッパークラスを作成する
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 - プロパティがデータベースレベルで計算されるかどうかを指定します。数値のPKはDatabaseGeneratedOption.Identityです。デフォルトでは、そうしたくない場合はDatabaseGeneratedOption.Noneを指定する必要があります。
- HasMaxLength - 文字列の長さを制限します。
- IsRequired - プロパティを再クエリとしてマークします。
- HasPrecision - 小数点以下の桁数の精度を指定できます。
- Ignore - プロパティを完全に無視し、データベースにマップしません。 FullNameは無視されました。なぜなら、この列をテーブルに入れたくないからです。
- ToTable - モデルのテーブル名とスキーマ名(オプション)を指定します。
- HasColumnName - プロパティを列名に関連付けます。プロパティー名と列名が同一である場合、これは必要ありません。
ステップ3:マッピングクラスを構成に追加します。
マッパークラスを使用するようにEntityFrameworkに指示する必要があります。これを行うには、 OnModelCreatingメソッドのmodelBuilder.Configurationsに追加する必要があります。
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
を実行して外部キー名を明示的に設定MapKey
ます。この例では、Employer_Idの列名になったのは今ではEmployerIdです。