エンティティのプロパティ

モデル内の各エンティティ型には一連のプロパティがあり、EF Core は、それらのプロパティをデータベースから読み取ったりデータベースに書き込んだりします。 リレーショナル データベースを使用している場合、エンティティのプロパティは、テーブルの列にマッピングされます。

含まれるプロパティと除外されるプロパティ

規約上、ゲッターとセッターを備えたパブリック プロパティはすべてモデルに追加されます。

次のようにすることで、特定のプロパティを除外することができます。

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [NotMapped]
    public DateTime LoadedFromDatabase { get; set; }
}

列名

規約上、リレーショナル データベースを使用している場合、エンティティのプロパティは、そのプロパティと同じ名前のテーブル列にマッピングされます。

別の名前で列を構成したい場合は、次のコード スニペットで、そのようにすることができます。

public class Blog
{
    [Column("blog_id")]
    public int BlogId { get; set; }

    public string Url { get; set; }
}

列のデータ型

リレーショナル データベースを使用している場合、データ型は、データベース プロバイダーによって、プロパティの .NET 型に応じて選択されます。 また、構成されている最大長、プロパティが主キーの一部になっているかどうかなど、他のメタデータも考慮されます。

たとえば、SQL Server では、DateTime プロパティが datetime2(7) 列に、string プロパティが nvarchar(max) 列 (キーとして使用されるプロパティの場合は nvarchar(450)) にマッピングされます。

また、自分で列を構成して、列の厳密なデータ型を指定することもできます。 たとえば、次のコードでは、最大長を 200 とする非 Unicode 文字列として Url を、また、有効桁数が 5 で小数点以下桁数が 2 の decimal として Rating を構成しています。

public class Blog
{
    public int BlogId { get; set; }

    [Column(TypeName = "varchar(200)")]
    public string Url { get; set; }

    [Column(TypeName = "decimal(5, 2)")]
    public decimal Rating { get; set; }
}

最大長

最大長を構成すると、特定のプロパティに対して選択する適切な列データ型についてのヒントが、データベース プロバイダーに与えられます。 最大長の適用対象となるのは、stringbyte[] などの配列データ型のみです。

注意

Entity Framework は、プロバイダーにデータを渡す前の最大長の検証を一切行いません。 プロバイダー側またはデータ ストア側で適宜検証する必要があります。 たとえば、SQL Server をターゲットにする場合、最大長を超えると、それ以上のデータは基になる列のデータ型で格納できないので例外が発生します。

次の例では、最大長として 500 を構成しているので、SQL Server には nvarchar(500) 型の列が作成されます。

public class Blog
{
    public int BlogId { get; set; }

    [MaxLength(500)]
    public string Url { get; set; }
}

有効桁数と小数点以下桁数

一部のリレーショナル データ型では、有効桁数と小数点以下桁数のファセットがサポートされています。どのような値を格納できるのか、また、列にどの程度の記憶域が必要なのかが、それらのファセットによって制御されます。 有効桁数と小数点以下桁数がどのデータ型でサポートされるかはデータベースによって異なりますが、ほとんどのデータベースでは、decimal 型と DateTime 型でこれらのファセットがサポートされます。 decimal のプロパティでは、列に格納される値を表現するために必要な最大桁数が有効桁数によって定義され、また、小数点以下に必要な最大桁数が小数点以下桁数によって定義されます。 DateTime のプロパティでは、秒の小数部を表現するために必要な最大桁数が有効桁数によって定義され、小数点以下桁数は使用されません。

注意

Entity Framework は、プロバイダーにデータを渡す前の有効桁数または小数点以下桁数の検証を一切行いません。 プロバイダー側またはデータ ストア側で適宜検証する必要があります。 たとえば、SQL Server をターゲットにする場合、datetime データ型の列では、有効桁数の設定が許可されないのに対し、datetime2 型の列では、0 桁から 7 桁の範囲で有効桁数を設定できます。

以下の例で、Score プロパティは有効桁数が 14、小数点以下桁数が 2 として構成されているので、SQL Server には decimal(14,2) 型の列が、また LastUpdated プロパティは有効桁数が 3 として構成されているので datetime2(3) 型の列が作成されます。

注意

有効桁数と小数点以下桁数を構成するためのデータ注釈は、EF Core 6.0 で導入されました。

public class Blog
{
    public int BlogId { get; set; }
    [Precision(14, 2)]
    public decimal Score { get; set; }
    [Precision(3)]
    public DateTime LastUpdated { get; set; }
}

小数点以下桁数を定義するには、必ず先に有効桁数を定義する必要があります。したがって、小数点以下桁数を定義するためのデータ注釈は [Precision(precision, scale)] となります。

Unicode

一部のリレーショナル データベースでは、Unicode と非 Unicode のテキスト データを表現するための型が別々に存在します。 たとえば、SQL Server では、UTF-16 の Unicode データを表現するために nvarchar(x) が、また 非 Unicode データを表現するために varchar(x) が使用されます (ただし、nvarchar(x)に関するページの注意を参照)。 この概念をサポートしないデータベースの場合、この構成を行っても期待した効果は得られません。

テキストのプロパティは、既定では Unicode として構成されます。 非 Unicode として列を構成するには、次のようにします。

注意

Unicode を構成するためのデータ注釈は、EF Core 6.0 で導入されました。

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Unicode(false)]
    [MaxLength(22)]
    public string Isbn { get; set; }
}

必須および省略可能なプロパティ

プロパティは、null の格納が有効である場合、省略可能と見なされます。 プロパティに代入する値として null が有効でない場合は、必須のプロパティと見なされます。 リレーショナル データベースのスキーマにマッピングする際、必須のプロパティは Null 非許容の列として、また省略可能なプロパティは Null 許容型の列として作成されます。

規約

規約上、対応する .NET 型が Null 値を格納できるプロパティは省略可能として構成されるのに対し、対応する .NET 型が Null 値を格納できないプロパティは必須として構成されます。 たとえば、.NET の値型 (intdecimalbool など) のプロパティはすべて 必須として構成され、Null 値が許容される .NET の値型 (int?decimal?bool? など) のプロパティはすべて 省略可能として構成されます。

C# 8 では、Null 許容参照型 (NRT) と呼ばれる新機能が導入され、参照型の値として Null が有効かどうかを示す注釈を設定できるようになりました。 この機能は、既定では無効になっており、EF Core の動作に次のように作用します。

  • Null 許容参照型が無効 (既定) の場合、.NET 参照型のプロパティはすべて規約により省略可能として構成されます (string など)。
  • Null 許容参照型が有効の場合、プロパティは、対応する .NET 型における C# の Null 値の許容に基づいて構成されます。つまり、string? は省略可能として構成されますが、string は必須として構成されます。

次の例は、必須および省略可能なプロパティを含んだエンティティ型を、Null 許容参照機能が無効 (既定) の場合と有効の場合について示しています。

public class CustomerWithoutNullableReferenceTypes
{
    public int Id { get; set; }

    [Required] // Data annotations needed to configure as required
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; } // Data annotations needed to configure as required

    public string MiddleName { get; set; } // Optional by convention
}

Null 許容参照型の使用をお勧めします。C# コードで表現された Null 値の許容が EF Core のモデルやデータベースに対しスムーズに引き継がれ、fluent API やデータ注釈を使用して同じ概念を 2 回表現する手間が省けます。

注意

既存のプロジェクトで Null 許容参照型を有効にする場合は注意が必要です。それまで省略可能として構成されていた参照型のプロパティは、明示的に Null 許容として注釈を設定しない限り、必須として構成されます。 リレーショナル データベースのスキーマを管理する際、このことが原因で、データベース列の Null 値の許容が変わってしまうような移行が生成されることがあります。

Null 許容参照型、そして EF Core におけるその使用方法について詳しくは、この機能専用のドキュメント ページを参照してください。

明示的な構成

規約では省略可能となるプロパティでも、次のように構成すれば必須にすることができます。

public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

列の照合順序

注意

この機能は EF Core 5.0 で導入されました。

テキスト列には、比較と並べ替えの方法を決定する照合順序を定義できます。 たとえば次のコード スニペットでは、SQL Server の列を、大文字と小文字が区別されない列として構成しています。

modelBuilder.Entity<Customer>().Property(c => c.Name)
    .UseCollation("SQL_Latin1_General_CP1_CI_AS");

データベース内のすべての列に対して特定の照合順序を使用する必要がある場合は、データベース レベルで照合順序を定義してください。

EF Core における照合順序のサポート全般については、照合順序のドキュメント ページに記載されています。

列のコメント

任意のテキスト コメントを設定できます。設定したコメントは、データベースの列に対して設定されるので、データベース内のスキーマを文書化することができます。

注意

データ注釈を用いたコメント設定は、EF Core 5.0 で導入されました。

public class Blog
{
    public int BlogId { get; set; }

    [Comment("The URL of the blog")]
    public string Url { get; set; }
}

列の順序

注意

この機能は EF Core 6.0 で導入されました。

既定では、Migrations を使用してテーブルを作成した場合、列順は最初に主キー列、次にエンティティ型と所有型のプロパティ、最後に基本データ型のプロパティという順序になります。 ただし、別の列順を自分で指定することもできます。

public class EntityBase
{
    [Column(Order = 0)]
    public int Id { get; set; }
}

public class PersonBase : EntityBase
{
    [Column(Order = 1)]
    public string FirstName { get; set; }

    [Column(Order = 2)]
    public string LastName { get; set; }
}

public class Employee : PersonBase
{
    public string Department { get; set; }
    public decimal AnnualSalary { get; set; }
}

Fluent API を使用することによって、異なるプロパティの属性で同じ順序番号が指定されている場合の競合の解決を含め、属性で行われる順序をオーバーライドすることができます。

一般的に、ほとんどのデータベースでは、列の順序付けがサポートされるのはテーブルの作成時のみであることに注意してください。 つまり、列の順序属性を使用して、既存テーブルの列の順序を変更することはできません。