Entity Framework
コードの最初のデータアノテーション
サーチ…
備考
Entity Framework Code-Firstは、DataAnnotation属性のセットを提供します。この属性は、ドメインクラスとプロパティに適用できます。 DataAnnotation属性は、デフォルトのコード・ファースト規則をオーバーライドします。
- System.ComponentModel.DataAnnotationsには、NULL可能性または列のサイズに影響する属性が含まれています。
- System.ComponentModel.DataAnnotations.Schema名前空間には、データベースのスキーマに影響を与える属性が含まれています。
注: DataAnnotationsは、構成オプションのサブセットのみを提供します。 Fluent APIは、Code-Firstで利用可能なすべての設定オプションを提供します。
[Key]属性
キーは、データベーステーブル内の各行/レコードを一意に識別するテーブル内のフィールドです。
この属性を使用して、デフォルトのコードファースト規則を上書きします 。プロパティに適用すると、このクラスの主キー列として使用されます 。
using System.ComponentModel.DataAnnotations;
public class Person
{
[Key]
public int PersonKey { get; set; } // <- will be used as primary key
public string PersonName { get; set; }
}
複合主キーが必要な場合は、[Key]属性を複数のプロパティに追加することもできます。複合キー内の列の順序は、[ キー、列(Order = x)]の形式で指定する必要があります。
using System.ComponentModel.DataAnnotations;
public class Person
{
[Key, Column(Order = 0)]
public int PersonKey1 { get; set; } // <- will be used as part of the primary key
[Key, Column(Order = 1)]
public int PersonKey2 { get; set; } // <- will be used as part of the primary key
public string PersonName { get; set; }
}
[Key]属性がなければ 、EntityFrameworkは "Id"または "{ClassName} Id"という名前のプライマリキーとしてクラスのプロパティを使用するデフォルトの規約に戻ります。
public class Person
{
public int PersonID { get; set; } // <- will be used as primary key
public string PersonName { get; set; }
}
[必須]属性
ドメインクラスのプロパティに適用すると、データベースはNOT NULL列を作成します。
using System.ComponentModel.DataAnnotations;
public class Person
{
public int PersonID { get; set; }
[Required]
public string PersonName { get; set; }
}
NOT NULL制約を持つ結果のカラム:
注:検証属性としてasp.net-mvcとともに使用することもできます。
[MaxLength]および[MinLength]属性
[MaxLength(int)]属性は、ドメインクラスの文字列型または配列型のプロパティに適用できます。 Entity Frameworkは、列のサイズを指定された値に設定します。
using System.ComponentModel.DataAnnotations;
public class Person
{
public int PersonID { get; set; }
[MinLength(3), MaxLength(100)]
public string PersonName { get; set; }
}
指定された列の長さを持つ結果の列:
[MinLength(int)]属性は検証属性ですが、データベース構造には影響しません。 PersonNameの長さが3文字未満のPersonを挿入/更新しようとすると、このコミットは失敗します。私たちが処理する必要のあるDbUpdateConcurrencyException
を取得します。
using (var db = new ApplicationDbContext())
{
db.Staff.Add(new Person() { PersonName = "ng" });
try
{
db.SaveChanges();
}
catch (DbEntityValidationException ex)
{
//ErrorMessage = "The field PersonName must be a string or array type with a minimum length of '3'."
}
}
[MaxLength]および[MinLength]属性は、検証属性としてasp.net-mvcとともに使用することもできます。
[範囲(最小、最大)]属性
プロパティの数値の最小値と最大値の範囲を指定します。
using System.ComponentModel.DataAnnotations;
public partial class Enrollment
{
public int EnrollmentID { get; set; }
[Range(0, 4)]
public Nullable<decimal> Grade { get; set; }
}
Gradeに範囲外の値を挿入/更新しようとすると、このコミットは失敗します。私たちが処理する必要のあるDbUpdateConcurrencyException
を取得します。
using (var db = new ApplicationDbContext())
{
db.Enrollments.Add(new Enrollment() { Grade = 1000 });
try
{
db.SaveChanges();
}
catch (DbEntityValidationException ex)
{
// Validation failed for one or more entities
}
}
検証属性としてasp.net-mvcとともに使用することもできます。
結果:
[DatabaseGenerated]属性
データベースがプロパティの値を生成する方法を指定します。可能な値は3つあります。
-
None
は、値がデータベースによって生成されないことを指定します。 -
Identity
は、列がIDの列であり、通常は整数の主キーに使用されることを指定します。 -
Computed
は、データベースが列の値を生成することを指定します。
値がNone
以外の場合、Entity Frameworkはプロパティに対する変更をデータベースにコミットしません。
デフォルトでは( StoreGeneratedIdentityKeyConvention
基づいて)、整数キーのプロパティはID列として扱われます。この規則をオーバーライドして非同一列として扱うには、 DatabaseGenerated
属性にNone
ます。
using System.ComponentModel.DataAnnotations.Schema;
public class Foo
{
[Key]
public int Id { get; set; } // identity (auto-increment) column
}
public class Bar
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; } // non-identity column
}
次のSQLは、計算カラムを持つテーブルを作成します。
CREATE TABLE [Person] (
Name varchar(100) PRIMARY KEY,
DateOfBirth Date NOT NULL,
Age AS DATEDIFF(year, DateOfBirth, GETDATE())
)
GO
上記の表のレコードを表すエンティティを作成するには、 DatabaseGenerated
属性の値をComputed
する必要があります。
[Table("Person")]
public class Person
{
[Key, StringLength(100)]
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int Age { get; set; }
}
[NotMapped]属性
コード・ファースト・コンベンションでは、Entity Frameworkは、サポートされているデータ型であり、ゲッターとセッターの両方を持つすべてのパブリックプロパティの列を作成します。 [NotMapped]注釈は、我々がデータベーステーブルの列を使用しない任意のプロパティに適用する必要があります。
私たちがデータベースに保存したくないプロパティの例は、姓と名に基づいた生徒のフルネームです。これはオンザフライで計算することができ、データベースに格納する必要はありません。
public string FullName => string.Format("{0} {1}", FirstName, LastName);
"FullName"プロパティにはgetterとsetterがありません 。したがって、既定では、Entity Frameworkはデフォルトの列を作成しません 。
私たちがデータベースに保存したくないプロパティの別の例は、学生の "AverageGrade"です。オンデマンドでAverageGradeを取得することは望ましくありません。その代わりに、それを計算するルーチンがあるかもしれません。
[NotMapped]
public float AverageGrade { set; get; }
"AverageGrade"に[NotMapped]注釈を付ける必要があります。そうしないと、Entity Frameworkによって列が作成されます。
using System.ComponentModel.DataAnnotations.Schema;
public class Student
{
public int Id { set; get; }
public string FirstName { set; get; }
public string LastName { set; get; }
public string FullName => string.Format("{0} {1}", FirstName, LastName);
[NotMapped]
public float AverageGrade { set; get; }
}
上記のエンティティについては、 DbMigration.cs
内に表示されDbMigration.cs
CreateTable(
"dbo.Students",
c => new
{
Id = c.Int(nullable: false, identity: true),
FirstName = c.String(),
LastName = c.String(),
})
.PrimaryKey(t => t.Id);
およびSQL Server Management Studio
[表]属性
[Table("People")]
public class Person
{
public int PersonID { get; set; }
public string PersonName { get; set; }
}
Entity Frameworkに、特定のテーブル名を使用するように指示します(つまり、 Person
またはPersons
)
[Table]属性を使用してテーブルのスキーマを指定することもできます
[Table("People", Schema = "domain")]
[列]属性
public class Person
{
public int PersonID { get; set; }
[Column("NameOfPerson")]
public string PersonName { get; set; }
}
Entity Frameworkに、プロパティの名前を使用する代わりに、特定の列名を使用するように指示します。また、データベースのデータ型と列の順序を表で指定することもできます。
[Column("NameOfPerson", TypeName = "varchar", Order = 1)]
public string PersonName { get; set; }
[Index]属性
public class Person
{
public int PersonID { get; set; }
public string PersonName { get; set; }
[Index]
public int Age { get; set; }
}
列または列のセットのデータベースインデックスを作成します。
[Index("IX_Person_Age")]
public int Age { get; set; }
これにより、特定の名前の索引が作成されます。
[Index(IsUnique = true)]
public int Age { get; set; }
これにより一意のインデックスが作成されます。
[Index("IX_Person_NameAndAge", 1)]
public int Age { get; set; }
[Index("IX_Person_NameAndAge", 2)]
public string PersonName { get; set; }
これにより、2つの列を使用して複合インデックスが作成されます。これを行うには、同じインデックス名を指定し、列の順序を指定する必要があります。
注 :Index属性は、Entity Framework 6.1で導入されました。以前のバージョンを使用している場合、このセクションの情報は適用されません。
[ForeignKey(string)]属性
EFの規則に従わない外部キーが必要な場合は、カスタム外部キー名を指定します。
public class Person
{
public int IdAddress { get; set; }
[ForeignKey(nameof(IdAddress))]
public virtual Address HomeAddress { get; set; }
}
これは、同じエンティティタイプに対して複数の関係がある場合にも使用できます。
using System.ComponentModel.DataAnnotations.Schema;
public class Customer
{
...
public int MailingAddressID { get; set; }
public int BillingAddressID { get; set; }
[ForeignKey("MailingAddressID")]
public virtual Address MailingAddress { get; set; }
[ForeignKey("BillingAddressID")]
public virtual Address BillingAddress { get; set; }
}
なしでForeignKey
属性、EFはそれら混同得るかもしれないとの値を使用BillingAddressID
フェッチする際MailingAddress
、またはそれだけで(のような、独自の命名規則に基づいて、列に別の名前を思いつくかもしれませんAddress_MailingAddress_Id
)とすることを使用するようにしてください代わりに(既存のデータベースでこれを使用している場合はエラーになります)。
[StringLength(int)]属性
using System.ComponentModel.DataAnnotations;
public class Post
{
public int Id { get; set; }
[StringLength(100)]
public string Title { get; set;}
[StringLength(300)]
public string Abstract { get; set; }
public string Description { get; set; }
}
文字列フィールドの最大長を定義します。
注 :検証属性としてasp.net-mvcとともに使用することもできます。
[タイムスタンプ]属性
[TimeStamp]属性は、指定されたEntityクラスの1バイトの配列プロパティにのみ適用できます。 Entity Frameworkは、そのプロパティのデータベーステーブルにnullを許可しないタイムスタンプ列を作成します。 Entity Frameworkは自動的にこのTimeStamp列を同時性チェックで使用します。
using System.ComponentModel.DataAnnotations.Schema;
public class Student
{
public int Id { set; get; }
public string FirstName { set; get; }
public string LastName { set; get; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
[ConcurrencyCheck]属性
この属性はclassプロパティに適用されます。 ConcurrencyCheck属性は、既存の列を並行性検査に使用し、並行性のために別々のタイムスタンプ列を使用しない場合に使用できます。
using System.ComponentModel.DataAnnotations;
public class Author
{
public int AuthorId { get; set; }
[ConcurrencyCheck]
public string AuthorName { get; set; }
}
上の例から、ConcurrencyCheck属性はAuthorクラスのAuthorNameプロパティに適用されます。したがって、コード・ファーストは、楽観的な並行性をチェックするために、更新コマンド(Where句)にAuthorName列を含めます。
[InverseProperty(string)]属性
using System.ComponentModel.DataAnnotations.Schema;
public class Department
{
...
public virtual ICollection<Employee> PrimaryEmployees { get; set; }
public virtual ICollection<Employee> SecondaryEmployees { get; set; }
}
public class Employee
{
...
[InverseProperty("PrimaryEmployees")]
public virtual Department PrimaryDepartment { get; set; }
[InverseProperty("SecondaryEmployees")]
public virtual Department SecondaryDepartment { get; set; }
}
InversePropertyは、2つのエンティティ間に複数の 双方向関係が存在する場合に、2 つの方法関係を識別するために使用できます。
これはEntity Frameworkに、ナビゲーションプロパティが相手側のプロパティと一致する必要があることを通知します。
エンティティフレームワークは、2つのエンティティ間に複数の双方向関係が存在する場合、どのナビゲーションプロパティが他の側のどのプロパティにマップするかを認識しません。
関連するクラスの対応するナビゲーションプロパティの名前がそのパラメータとして必要です。
これは、同じタイプの他のエンティティとの関係を持つエンティティに対しても使用でき、再帰的関係を形成します。
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class TreeNode
{
[Key]
public int ID { get; set; }
public int ParentID { get; set; }
...
[ForeignKey("ParentID")]
public TreeNode ParentNode { get; set; }
[InverseProperty("ParentNode")]
public virtual ICollection<TreeNode> ChildNodes { get; set; }
}
ForeignKey
属性を使用して、表の外部キーに使用される列を指定することにも注意してください。最初の例では、 Employee
クラスの2つのプロパティに、列名を定義するためにForeignKey
属性が適用されている可能性があります。
[複合型]属性
using System.ComponentModel.DataAnnotations.Schema;
[ComplexType]
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
public class Blog
{
...
public BlogDetails BlogDetail { get; set; }
}
Entity Frameworkでクラスを複合型としてマークします。
複雑なタイプ(またはドメイン駆動型設計におけるバリューオブジェクト )は、単独では追跡できませんが、エンティティの一部として追跡されます。これは、例のBlogDetailsにキープロパティがない理由です。
これらは、複数のクラスにわたってドメインエンティティを記述し、それらのクラスを完全なエンティティに階層化するときに役立ちます。