假设我们正在使用 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; }
}
}
像这样,CAddress
将会主要的结束这种 1:0..1 的关系。
接下来我们将连接字符串添加到Web.Config(我使用MSSQL 2008 R2),制作一个使用该模型的控制器,运行。 EF Code First 按预期为我们创建了表:
所以,假设我们犯了一个错误,事实上我们想要CUser
to be 主要的这种 0..1:1 关系的结束。所以我们做出改变:
...
[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,身份:真实));
因此,CUsers.ID 现在必须成为数据库中的身份。让我们将这些更改提交到数据库:
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 的迁移没有给出 SQL 指令,成为数据库中的标识列。所以,正因为如此,就有一个问题:
(updated database)
因此,用户现在是主体端,并且必须具有 ID Identity:“YES”标志,但 Identity 仍然是“NO”。地址是从属端,必须具有 ID 身份“NO”,但仍然是“YES”。所以我无法将新用户添加到用户表中,因为不会为新实例生成新ID。
如果我删除整个数据库,EF Code First 会正确地从头开始创建新表,因此这只是迁移的问题。
在这种情况下我该怎么办?这是 EF 迁移错误吗?