Entity Framework
Entity-Frameworkコードの最初の移行
サーチ…
移行を有効にする
エンティティフレームワークでコードファーストマイグレーションを有効にするには、次のコマンドを使用します。
Enable-Migrations
パッケージマネージャコンソールで
EFによって管理されるデータベースオブジェクトを含む有効なDbContext
実装が必要です。この例では、データベースコンテキストにオブジェクトBlogPost
とAuthor
が含まれます。
internal class DatabaseContext: DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; }
}
コマンドを実行すると、次の出力が表示されます。
PM> Enable-Migrations
Checking if the context targets an existing database...
Code First Migrations enabled for project <YourProjectName>.
PM>
さらに、新しいフォルダMigrations
は、1つのファイルConfiguration.cs
とともに表示されます。
次のステップは、最初のデータベースを作成する最初のデータベース移行スクリプトを作成することです(次の例を参照)。
最初の移行を追加する
移行を有効にしたら( この例を参照してください)、すべてのデータベーステーブル、インデックス、および接続の初期作成を含む最初の移行を作成できるようになりました。
このコマンドを使用して移行を作成することができます
Add-Migration <migration-name>
このコマンドは、移行の適用と削除に使用される2つのメソッドUp
とDown
を含む新しいクラスを作成します。
上記の例に基づいてコマンドを適用して、 Initialというマイグレーションを作成します。
PM> Add-Migration Initial
Scaffolding migration 'Initial'.
The Designer Code for this migration file includes a snapshot of your current Code
First model. This snapshot is used to calculate the changes to your model when you
scaffold the next migration. If you make additional changes to your model that you
want to include in this migration, then you can re-scaffold it by running
'Add-Migration Initial' again.
新しいファイルタイムスタンプ _Initial.csが作成されます(重要なものだけがここに表示されます)。
public override void Up()
{
CreateTable(
"dbo.Authors",
c => new
{
AuthorId = c.Int(nullable: false, identity: true),
Name = c.String(maxLength: 128),
})
.PrimaryKey(t => t.AuthorId);
CreateTable(
"dbo.BlogPosts",
c => new
{
Id = c.Int(nullable: false, identity: true),
Title = c.String(nullable: false, maxLength: 128),
Message = c.String(),
Author_AuthorId = c.Int(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Authors", t => t.Author_AuthorId)
.Index(t => t.Author_AuthorId);
}
public override void Down()
{
DropForeignKey("dbo.BlogPosts", "Author_AuthorId", "dbo.Authors");
DropIndex("dbo.BlogPosts", new[] { "Author_AuthorId" });
DropTable("dbo.BlogPosts");
DropTable("dbo.Authors");
}
ご覧のように、メソッドUp()
2つのテーブルAuthors
とBlogPosts
が作成され、それに応じてフィールドが作成されます。また、2つのテーブルの関係は、フィールドAuthor_AuthorId
追加することによって作成されます。反対に、メソッドDown()
は、移行アクティビティを取り消そうとします。
移行に自信がある場合は、次のコマンドを使用して移行をデータベースに適用できます。
Update-Database
すべての保留中の移行(この場合はInitial -migration)がデータベースに適用された後、シードメソッドが適用されます(適切な例)
PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target
database.
Applying explicit migrations: [201609302203541_Initial].
Applying explicit migration: 201609302203541_Initial.
Running Seed method.
SQLエクスプローラで、アクティビティの結果を確認できます。
Add-Migration
とUpdate-Database
のコマンドAdd-Migration
は、アクティビティを調整するためのいくつかのオプションがあります。すべてのオプションを表示するには、
get-help Add-Migration
そして
get-help Update-Database
移行中のデータのシード
移行を有効にして作成した後は、データベース内のデータを最初に入力または移行する必要があります。いくつかの可能性がありますが、単純な移行の場合は、 enable-migrations
呼び出した後に作成されるConfigurationファイルのSeed()メソッドを使用できます。
Seed()
関数はデータベースコンテキストをパラメータとして取得し、この関数内でEF操作を実行できます。
protected override void Seed(Model.DatabaseContext context);
Seed()
内では、すべてのタイプのアクティビティを実行できます。何らかの障害が発生した場合、完全なトランザクション(適用されたパッチも)がロールバックされます。
表が空の場合にのみデータを作成する関数の例は、次のようになります。
protected override void Seed(Model.DatabaseContext context)
{
if (!context.Customers.Any()) {
Customer c = new Customer{ Id = 1, Name = "Demo" };
context.Customers.Add(c);
context.SaveData();
}
}
EF開発者が提供する優れた機能は、拡張メソッドAddOrUpdate()
です。この方法では、プライマリキーに基づいてデータを更新したり、データが存在しない場合はデータを挿入することができます(この例は、生成されたConfiguration.csのソースコードから取得されます)。
protected override void Seed(Model.DatabaseContext context)
{
context.People.AddOrUpdate(
p => p.FullName,
new Person { FullName = "Andrew Peters" },
new Person { FullName = "Brice Lambson" },
new Person { FullName = "Rowan Miller" }
);
}
最後のパッチ適用後に
Seed()
が呼び出されることに注意してください。パッチ中にデータを移行またはシードする必要がある場合は、他のアプローチを使用する必要があります。
移行中にSql()を使用する
たとえば、既存の列を非必須から必須に移行する予定です。この場合、変更されたフィールドが実際にNULL
いる行に対しては、移行でいくつかのデフォルト値を入力する必要がありNULL
。デフォルト値がシンプル(例えば "0")の場合、カラム定義でdefault
またはdefaultSql
プロパティを使用することができdefault
。それほど簡単ではない場合は、移行のUp()
またはDown()
メンバー関数でSql()
関数を使用できます。
ここに例があります。データセットの一部として電子メールアドレスを含むクラスAuthorを想定します。これで、電子メールアドレスを必須フィールドにすることにしました。既存の列を移行するには、 [email protected]
ようなダミーの電子メールアドレスを作成するというスマートな考え方があります。完全な名前はスペースなしの完全な名前です。 [Required]
Email
[Required]
フィールドに[Required]
属性を追加すると、次の移行が作成されます。
public partial class AuthorsEmailRequired : DbMigration
{
public override void Up()
{
AlterColumn("dbo.Authors", "Email", c => c.String(nullable: false, maxLength: 512));
}
public override void Down()
{
AlterColumn("dbo.Authors", "Email", c => c.String(maxLength: 512));
}
}
これは、いくつかのNULLフィールドがデータベース内にある場合には失敗します。
値 'NULL'を列 'Email'、表 'App.Model.DatabaseContext.dbo.Authors'に挿入できません。列はNULLを許可しません。 UPDATEに失敗します。
AlterColumn
コマンドの前に次のように追加すると、
Sql(@"Update dbo.Authors
set Email = REPLACE(name, ' ', '') + N'@example.com'
where Email is null");
update-database
呼び出しが成功し、テーブルは次のようになります(サンプルデータが表示されます)。
その他の使用法
データベース内のすべてのタイプのDMLおよびDDLアクティビティーにSql()
関数を使用できます。移行トランザクションの一部として実行されます。 SQLに障害が発生すると、完全な移行が失敗し、ロールバックが実行されます。
コード内で "Update-Database"を実行する
非開発環境で動作するアプリケーションでは、データベースの更新が必要なことがよくあります。 Add-Migration
コマンドを使用してデータベースパッチを作成した後は、他の環境でも更新プログラムを実行する必要があります。
一般的に直面する課題は次のとおりです。
- 運用環境にVisual Studioがインストールされていない
- 実際の接続/顧客環境には接続が許可されていません。
回避策は、実行する更新を確認し、それらを順番に実行する次のコードシーケンスです。エラーが発生してもデータが失われないように、適切なトランザクションと例外処理を行ってください。
void UpdateDatabase(MyDbConfiguration configuration) {
DbMigrator dbMigrator = new DbMigrator( configuration);
if ( dbMigrator.GetPendingMigrations().Any() )
{
// there are pending migrations run the migration job
dbMigrator.Update();
}
}
MyDbConfiguration
はあなたのソースのどこかであなたの移行セットアップです:
public class MyDbConfiguration : DbMigrationsConfiguration<ApplicationDbContext>
初期エンティティフレームワークコードの最初の移行手順
- コンソールアプリケーションを作成します。
- 「Package Manager Console」で
Install-Package EntityFramework
実行して、EntityFrameworkのnugetパッケージをInstall-Package EntityFramework
。 - app.configファイルに接続文字列を追加します。接続に
providerName="System.Data.SqlClient"
を含めることが重要です。 - あなたが望むようにパブリッククラスを作成します。例えば、 "
Blog
" - DbContextを継承するContextClassを作成すると、「
BlogContext
」のようなものがあります - DbSet型のコンテキストでプロパティを定義します。次のようなものがあります:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
}
public class BlogContext: DbContext
{
public BlogContext(): base("name=Your_Connection_Name")
{
}
public virtual DbSet<Blog> Blogs{ get; set; }
}
- コンストラクタ(ここではYour_Connection_Name)に接続名を渡すことが重要です。
- パッケージマネージャコンソールで、
Enable-Migration
コマンドを実行します。これにより、プロジェクトに移行フォルダが作成されます -
Add-Migration Your_Arbitrary_Migraiton_Name
コマンドを実行すると、Migrationsフォルダに、Up()とDown()の2つのメソッドを持つ移行クラスが作成されます。 - ブログテーブルを使用してデータベースを作成するには
Update-Database
コマンドを実行します