11

たとえば、EF Code First を使用していて、次の単純なモデルがあるとします。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace EFCodeFirstIdentityProblem.Models
{
    public class CAddress
    {
        public int ID { get; set; }

        public string Street { get; set; }
        public string Building { get; set; }

        public virtual CUser User { get; set; }
    }

    public class CUser
    {
        public int ID { get; set; }

        public string Name { get; set; }
        public string Age { get; set; }

        [Required]
        public virtual CAddress Address { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<CAddress> Addresses { get; set; }
        public DbSet<CUser> Users { get; set; }
    }
}


このように、この 1:0..1 関係の主なCAddress目的となります。次に、接続文字列を Web.Config に追加し (私は MSSQL 2008 R2 を使用しています)、このモデルを使用するコントローラーを作成し、実行します。EF Code First は期待どおりにテーブルを作成します。

ここに画像の説明を入力 ここに画像の説明を入力



ですから、私たちが間違いを犯したと仮定しましょう。実際には、この 0..1:1 の関係の主なCUser目的になりたいと考えています。そこで、次のように変更します。

        ...
        [Required]
        public virtual CUser User { get; set; }
        ...

        ...
        public virtual CAddress Address { get; set; }
        ...

ビルドしてから、パッケージ マネージャー コンソールで実行し、いくつかの移行を追加します。

PM> Enable-Migrations
Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201208021053489_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.
Code First Migrations enabled for project EFCodeFirstIdentityProblem.
PM> Add-Migration ChangeDependency
Scaffolding migration 'ChangeDependency'.
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 201208021157341_ChangeDependency' again.
PM> 

ここで、「ChangeDependency」の移行について与えられたものは次のとおりです。

namespace EFCodeFirstIdentityProblem.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class ChangeDependency : DbMigration
    {
        public override void Up()
        {
            DropForeignKey("dbo.CUsers", "ID", "dbo.CAddresses");
            DropIndex("dbo.CUsers", new[] { "ID" });
            AlterColumn("dbo.CAddresses", "ID", c => c.Int(nullable: false));
            AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false, identity: true)); //identity: true - this is important
            AddForeignKey("dbo.CAddresses", "ID", "dbo.CUsers", "ID");
            CreateIndex("dbo.CAddresses", "ID");
        }

        public override void Down()
        {
            DropIndex("dbo.CAddresses", new[] { "ID" });
            DropForeignKey("dbo.CAddresses", "ID", "dbo.CUsers");
            AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false));
            AlterColumn("dbo.CAddresses", "ID", c => c.Int(nullable: false, identity: true));
            CreateIndex("dbo.CUsers", "ID");
            AddForeignKey("dbo.CUsers", "ID", "dbo.CAddresses", "ID");
        }
    }
}

重要な部分は次のとおりです。

AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false, identity: true ));

したがって、CUsers.ID は DB の Identity になる必要があります。この変更を DB にコミットしましょう。

PM> 
PM> Update-Database -Verbose
Using StartUp project 'EFCodeFirstIdentityProblem'.
Using NuGet project 'EFCodeFirstIdentityProblem'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'EFTest' (DataSource: (local), Provider: System.Data.SqlClient, Origin: Configuration).
Applying code-based migrations: [201208021157341_ChangeDependency].
Applying code-based migration: 201208021157341_ChangeDependency.
ALTER TABLE [dbo].[CUsers] DROP CONSTRAINT [FK_dbo.CUsers_dbo.CAddresses_ID]
DROP INDEX [IX_ID] ON [dbo].[CUsers]
ALTER TABLE [dbo].[CAddresses] ALTER COLUMN [ID] [int] NOT NULL
ALTER TABLE [dbo].[CUsers] ALTER COLUMN [ID] [int] NOT NULL
ALTER TABLE [dbo].[CAddresses] ADD CONSTRAINT [FK_dbo.CAddresses_dbo.CUsers_ID] FOREIGN KEY ([ID]) REFERENCES [dbo].[CUsers] ([ID])
CREATE INDEX [IX_ID] ON [dbo].[CAddresses]([ID])
[Inserting migration history record]
Running Seed method.
PM> 

CUsers.ID が DB の Identity 列になる移行によって与えられる SQL 命令はありません。そのため、次のような問題があります。

(更新されたデータベース) ここに画像の説明を入力 ここに画像の説明を入力

したがって、ユーザーは現在プリンシパルエンドであり、ID Identity: "YES" フラグが必要ですが、Identity はまだ "NO" です。また、アドレスは依存エンドであり、ID ID は「NO」である必要がありますが、それでも「YES」です。したがって、新しいインスタンスに対して新しい ID が生成されないため、新しいユーザーをユーザー テーブルに追加できません。

データベース全体を削除すると、EF Code First は新しいテーブルを最初から適切に作成するため、これは移行のみの問題です。

この状況で私は何をしますか?これは EF 移行のバグですか?

4

1 に答える 1

22

別の問題があるため、バグかどうかはわかりません。既存の列を ID に変更したり、 ID を削除したりすることはできません。データを移動する必要があることを明確にするために、これは完全に手動の移行と見なされると想像できます。

于 2012-08-02T12:58:33.623 に答える