EF Code First 5.0.rc迁移不会更新Identity属性 [英] EF Code First 5.0.rc Migrations doesn`t update Identity property

查看:94
本文介绍了EF Code First 5.0.rc迁移不会更新Identity属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说,我们使用EF Code First,我们有这个简单的模型:

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

命名空间EFCodeFirstIdentityProblem.Models
{
public class CAddress
{
public int ID {get;组; }

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

public virtual CUser User {get;组; }
}

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

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

[必需]
public virtual CAddress Address {get;组; }
}

public class MyContext:DbContext
{
public DbSet< CAddress>地址{get;组; }
public DbSet< CUser>用户{get;组; }
}
}



喜欢这个, CAddress 将是这个1:0..1关系的主体结束。
接下来我们将连接字符串添加到Web.Config(我使用MSSQL 2008 R2),使一个控制器使用这个模型,运行。 EF代码首先根据预期为我们创建表格:








所以,我们假设我们犯了一个错误,实际上我们想要 CUser 主体此0..1:1关系的结尾。所以我们进行更改:

  ... 
[必需]
public virtual CUser User {get;组; }
...

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

Build,然后在Package Manager Console中运行并添加一些迁移:

  PM>启用迁移
检查上下文是否定位到现有数据库...
使用数据库初始化程序创建的检测到的数据库。脚手架迁移201208021053489_InitialCreate对应现有数据库。要使用自动迁移,请删除Migrations文件夹,并重新运行指定-EnableAutomaticMigrations参数的Enable-Migrations。
为项目EFCodeFirstIdentityProblem启用了代码优先迁移。
PM>添加迁移ChangeDependency
脚手架迁移ChangeDependency。
此迁移文件的Designer代码包含您当前的Code First模型的快照。当您支持下一次迁移时,此快照用于计算模型的更改。如果您要在此迁移中对要包含的模型进行其他更改,那么可以通过再次运行Add-Migration 201208021157341_ChangeDependency来重新构建它。
PM>

这里我们为ChangeDependency迁移提供了什么:

 命名空间EFCodeFirstIdentityProblem.Migrations 
{
using System;
使用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 - 这很重要
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);
}
}
}

导入和部分是: p>

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



所以CUsers.ID现在必须成为DB中的Identity。让我们把这个修改提交给DB:

  PM> 
PM>更新数据库-Verbose
使用StartUp项目'EFCodeFirstIdentityProblem'。
使用NuGet项目'EFCodeFirstIdentityProblem'。
指定'-Verbose'标志来查看应用于目标数据库的SQL语句。
目标数据库是:'EFTest'(DataSource:(本地)),Provider:System.Data.SqlClient,Origin:Configuration)。
应用基于代码的迁移:[201208021157341_ChangeDependency]。
应用基于代码的迁移: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])参考[dbo]。[CUsers]([ID])
CREATE INDEX [IX_ID] ON [dbo]。[CAddresses]([ID])
[插入迁移历史记录]
运行种子方法。
PM>

CUsers.ID的迁移没有给出SQL的SQL指令,成为DB中的Identity列。所以,因为这样做有一个问题:



(更新的数据库)



所以,用户现在是主体,必须有ID身份:YES标志,但身份仍然是否。而地址是依赖的,必须有ID身份NO,但仍然是是。所以我不能添加新的用户到用户表,因为新的实例不会生成新的ID。



如果我放弃整个数据库,EF Code First会创建新的表,划伤,所以这只是迁移问题。



在这种情况下我该怎么办?这是EF迁移错误吗?

解决方案

我不知道是否是一个错误,因为有另一个问题 - 你不能将现有列更改为身份或删除身份。我可以想象,这被认为是完全手动的迁移,以清楚说明您必须移动数据。


Say, we are using EF Code First and we have this simple model:

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; }
    }
}


Like this, CAddress would be principal end of this 1:0..1 relationship. Next we add connection string to Web.Config (I use MSSQL 2008 R2), make a controller that uses this model, run. EF Code First creates tables for us as expected:



So, let's assume we made a mistake, and in fact we want CUser to be principal end of this 0..1:1 relationship. So we make changes:

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

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

Build, then in Package Manager Console run and add some migration:

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> 

Here what we`ve been given for "ChangeDependency" migration:

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");
        }
    }
}

Importand part is:

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

So CUsers.ID must now become Identity in DB. Let's commit this changes to 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> 

There is no SQL instructions given by Migrations of CUsers.ID becoming Identity column in DB. So, because of this there is a problem:

(updated database)

So, User is principal end now, and has to have ID Identity: "YES" flag, but Identity is still "NO". And Address is dependent end, has to have ID Identity "NO", but is still "YES". So I can't add new User to User table, because new ID is not generated for new instance.

If I drop whole database, EF Code First creates new tables from scratch properly, so this is a problem only of Migrations.

What do I do in this situation? Is this EF Migrations bug?

解决方案

I'm not sure if it is a bug because there is another problem - you cannot alter existing column to identity or remove identity. I can imagine that this is considered as fully manual migration to make it clear that you must move data.

这篇关于EF Code First 5.0.rc迁移不会更新Identity属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆