|
連載:Entity Framework 4.1入門
第2回 EF 4.1の規約とデータベースの初期化方法
WINGSプロジェクト 土井 毅(監修:山田 祥寛)
2011/07/13 |
|
前回はEF 4.1の簡単なサンプルを構築することで、コード・ファーストによるアプリケーション開発が非常に簡潔なコードになることを確認できた。特に、「設定に勝る規約(Convention over Configuration:CoC)」の考え方に基づいて、設定ファイルの記述がほとんど必要なくなることが特徴だった。
今回は、コード・ファーストの規約を中心に、細かなカスタマイズ方法も含めて解説していく。
[コラム]EF 4.1言語パックのリリース |
2011年7月8日に日本語のサポートを含む「EF 4.1言語パック」がリリースされた。言語パックには、EF 4.1の、翻訳されたリソース(ドキュメントやエラー・メッセージなど)が含まれており、インストールすることで、Visual StudioのIntelliSenseでも日本語の情報が表示されるようになる。言語パックは、以下のリンク先からダウンロードできる。
|
■Entity Framework 4.1の規約とカスタマイズ方法
前回、コード・ファーストで使用されるいくつかの規約について解説したが、ここで主な規約を列挙してみよう。それぞれ、属性を用いて規約外の設定を行う方法についても記すので、参考にしてほしい。ここで紹介する属性はすべてSystem.ComponentModel.DataAnnotations名前空間に属している。
なお、この名前空間にはEF 3.5、EF 4から存在する属性と、EF 4.1から導入された属性が混在しており、すべての属性を使用するためには図1のように、System.ComponentModel.DataAnnotationsアセンブリへの参照を追加する必要がある(EF 4.1の属性のみであれば、前回追加したEntity Frameworkアセンブリの参照のみでよいが、EF 4以前の属性を使用する際には、System.ComponentModel.DataAnnotationsアセンブリへの参照が必要)。
|
図1 System.ComponentModel.DataAnnotationsアセンブリへの参照の追加 |
●接続文字列、データベース名
デフォルトでは、アプリケーション設定ファイルで定義された接続文字列のうち、コンテキスト・クラスと同じ名前のものが使用される。接続名が存在しない場合は、コンテキスト・クラスの完全修飾名(名前空間を含むクラス名)と同じ名前のデータベースを、ローカルのSQL Server Express上に作成して接続する。
このルールを変更するには、基底クラスDbContextのコンストラクタに以下のように指定すればよい。
public class ItemCatalog : DbContext
{
// 接続名の明示的な指定
public ItemCatalog()
: base("ItemDB") { }
……省略…… |
Public Class ItemCatalog
Inherits DbContext
Public Sub New()
' 接続名の明示的な指定
MyBase.New("ItemDB")
End Sub
……省略…… |
|
リスト1 使用する接続文字列の指定(上:ItemCatalog.cs、下:ItemCatalog.vb) |
なお、今回はSQL Server Compact 4.0上にデータを作成するため、App.configファイルに「ItemDB」という名前の接続文字列を定義しておく(リスト2)。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ItemDB"
connectionString="Data Source=|DataDirectory|SampleDatabase.sdf"
providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>
</configuration> |
|
リスト2 接続文字列の定義(App.config) |
●テーブル名
デフォルトではエンティティ・クラス名の(英語の)複数形がテーブル名にマッピングされる。ただし、日本語などが含まれている場合は、複数形化せず、クラス名がそのままテーブル名になる。
リスト3は「住所」という名前のエンティティ・クラスを定義した例である。そのままでは複数形化せず、「住所」という名前のテーブルが作成されるが、Table属性を付加することで、明示的にエンティティ・クラスと関連するテーブルの名前を指定できる。
// 明示的にテーブル名を指定
[Table("T_Addresses")]
public class 住所
{
……省略…… |
' 明示的にテーブル名を指定
<Table("T_Addresses")>
Public Class 住所
……省略…… |
|
リスト3 Table属性で明示的にテーブル名を指定(上:住所.cs、下:住所.vb) |
●フィールド名
デフォルトではエンティティ・クラスのプロパティがテーブルの同名のフィールドに、プロパティの型がデータ型にマッピングされる。
もしも明示的にフィールド名を指定したいならば、リスト4のようにフィールドにColumn属性を付加すればよい。また、Column属性のTypeNameプロパティでは、プロパティのデータ型を指定できる。このプロパティには、データベース依存のデータ型(例えば文字列を表す「nvarchar」)を指定している。
public class 住所
{
// データベース上のフィールド名とデータ型を指定
[Column("Zipcode", TypeName="nvarchar")]
public string 郵便番号 { get; set; }
……省略…… |
Public Class 住所
' データベース上のフィールド名とデータ型を指定
<Column("Zipcode", TypeName:="nvarchar")> *1
Public Property 郵便番号 As String
……省略…… |
|
リスト5 Column属性でフィールド名とデータ型を指定(上:住所.cs、下:住所.vb) |
*1 「:=」という表記はなじみが薄いかもしれないが、VB(Visual Basic)で属性の名前付き引数を指定するための記法である。 |
●主キー
デフォルトでは、「ID」あるいは「<クラス名>ID」という名前のプロパティ(大文字小文字は無視)が主キー・プロパティと見なされる。さらに主キー・プロパティがint/long/short型の場合は自動採番のフィールドになる(SQLの「IDENTITY」に対応)。
しかし、リスト6のようにKey属性を使用することで、上記の命名則に沿わないプロパティを主キー・プロパティに設定することもできる。
public class 住所
{
// 「Id」「住所Id」ではない「JushoId」を主キーに指定
[Key]
public int JushoId{ get; set; }
……省略…… |
Public Class 住所
' 「Id」「住所Id」ではない「JushoId」を主キーに指定
<Key()>
Public Property JushoId As Integer
……省略…… |
|
リスト6 Key属性による主キーの指定(上:住所.cs、下:住所.vb) |
またコード・ファーストでは、複合主キーにも対応しており、リスト7のように、Key属性とColumn属性のOrderプロパティを併用することで、複合主キーを定義できる。ここでは整数型のKey1プロパティと文字列型のKey2プロパティで複合主キーを定義し、それぞれOrderプロパティで主キーの順番を指定している。
public class CompositeKeyEntity
{
// 複合キー1つ目
[Key, Column(Order = 0)]
public int Key1{get;set;}
// 複合キー2つ目
[Key, Column(Order = 1)]
public string Key2 { get; set; }
public string Data { get; set; }
} |
Public Class CompositeKeyEntity
' 複合キー1つ目
<Key(), Column(Order:=0)>
Public Property Key1 As Integer
' 複合キー2つ目
<Key(), Column(Order:=1)>
Public Property Key2 As String
Public Property Data As String
End Class |
|
リスト7 複合キーの指定例(上:CompositeKeyEntity.cs、下:CompositeKeyEntity.vb) |
実際のデータベース上では、図2のようにKey1とKey2が複合キー(図中ではそれぞれ「PK」と表記)になる。
|
図2 複合キーの例 |
なお、コード・ファーストにおいても複合主キーはサポートされているものの、検索時に扱うデータ量の削減、および、ほかのテーブルから外部キーで参照する場合の構造をシンプルにするため、可能であれば別個に人工キー*2などを設けて主キーを割り当てるのが望ましいだろう。
*2 レコードごとに割り当てられる連番の整数値など、キーとしての役割のみを持つフィールドのこと。 |
●フィールドのNULL許容
Nullable型のプロパティの場合はNULL許容フィールドにマッピングされる。それ以外はNULLを許容しないフィールドになる(SQLの「NOT NULL」に対応)。