比如说,我们使用的是 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
成为这个 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, 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 中的标识列没有给出 SQL 指令。所以,正因为如此,有一个问题:
(更新的数据库)
因此,用户现在是主体端,并且必须具有 ID 身份:“是”标志,但身份仍然是“否”。并且地址是依赖端,必须有ID身份“NO”,但仍然是“YES”。所以我不能将新用户添加到用户表,因为没有为新实例生成新 ID。
如果我删除整个数据库,EF Code First 会正确地从头开始创建新表,所以这只是迁移的问题。
在这种情况下我该怎么办?这是 EF 迁移错误吗?