Code First 从 int 迁移到 Guid 主键问题

2024-05-01

我正在尝试将代码第一个 ID 列从“int”更改为“Guid”,当尝试运行迁移时,我收到以下消息:

Identity column 'CustomFieldId' must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable.

我这样定义列:

public partial class CustomField : BaseEntity
{

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid CustomFieldId { get; set; }

在 CustomFieldMapping.cs 中映射它,如下所示:

public CustomFieldMapping()
{
    //Primary key
    HasKey(t => t.CustomFieldId);

    //Constraints 
    Property(t => t.CustomFieldId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

生成的迁移正在尝试执行此操作:

public override void Up()
{
    DropForeignKey("dbo.CustomField", "CustomFormId", "dbo.CustomForm");
    DropForeignKey("dbo.CustomData", "CustomFieldId", "dbo.CustomField");
    DropForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm");
    DropIndex("dbo.CustomField", new[] { "CustomFormId" });
    DropIndex("dbo.CustomForm", new[] { "ParentFormId" });
    DropIndex("dbo.CustomData", new[] { "CustomFieldId" });
    DropPrimaryKey("dbo.CustomField");
    DropPrimaryKey("dbo.CustomForm");
    AlterColumn("dbo.CustomField", "CustomFieldId", c => c.Guid(nullable: false));
    AlterColumn("dbo.CustomField", "SortOrder", c => c.Int(nullable: false));
    AlterColumn("dbo.CustomForm", "CustomFormId", c => c.Guid(nullable: false));
    AlterColumn("dbo.CustomForm", "ParentFormId", c => c.Guid());
    AddPrimaryKey("dbo.CustomField", "CustomFieldId");
    AddPrimaryKey("dbo.CustomForm", "CustomFormId");
    CreateIndex("dbo.CustomField", "CustomForm_CustomFormId");
    CreateIndex("dbo.CustomForm", "ParentFormId");
    CreateIndex("dbo.CustomData", "CustomField_CustomFieldId");
    AddForeignKey("dbo.CustomField", "CustomForm_CustomFormId", "dbo.CustomForm", "CustomFormId");
    AddForeignKey("dbo.CustomData", "CustomField_CustomFieldId", "dbo.CustomField", "CustomFieldId");
    AddForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm", "CustomFormId");

我希望它是一个连续递增的 Uuid。我究竟做错了什么?


为了解决这个问题我使用了Sql()方法中的Up() and Down()迁移类的方法。 SQL命令字符串在Up()方法删除 ID 列上的主键约束,删除类型的 ID 列int然后添加一个新的 ID 列,其类型为Guid. The Down()方法做同样的事情但放弃Guid列并添加一个新的int column.

我在 Stack Overflow 上找到了一些解决方案,可以通过在查询窗口中运行 SQL 命令来解决“更改列类型”问题。针对您的评论:

我们只是想保持一个干净/清晰的迁移路径来跟踪 我们做了一些使用 SQL 并不总是容易的事情。

我在其中使用了 SQL 命令Up() and Down()迁移方法。对我来说,这个解决方案在我的项目中效果很好。

本答案底部的解决方案是由几个 Stack Overflow 问题/答案构建的。跳到此处仅查看代码。这是冗长的细节。

在迁移类中使用 SQL 命令

我找不到使用实体框架迁移方法的解决方案,例如AlterColumn() and DropColumn() ONLY.

而不是在迁移方法和命令中混合使用Sql()方法中,我使用了字符串中的所有 SQL 命令Sql()迁移方法。使用所有 SQL 命令可以更轻松地在 Visual Studio 或 SQL Server Management Studio 的查询窗口中进行测试。

The answer https://stackoverflow.com/questions/26535189/entity-framework-execute-sql-before-migrations由“Uchitha”给出了添加的起始步骤Sql()“所需迁移类中的方法。”

  1. 使用 Add-Migration 生成迁移类
  2. 使用与上面类似的代码更改类
  3. 使用更新数据库运行迁移

The Sql()答案中的方法示例如下所示:

Sql("UPDATE dbo.YourTable SET Column1 = 'VALUE1' "); 

更改列类型 - 一般步骤

我用的是answer https://stackoverflow.com/questions/14837168/ef5-code-first-changing-a-column-type-with-migrations通过“JustAnotherUserYouMayKnow”开始更改列类型的步骤。我没有明确遵循这一点,但它只提供了删除列并重新创建它的需要的基本框架。

  1. 使用您的新类型添加新列
  2. Use Sql()使用更新语句接管原始列中的数据
  3. 删除旧列
  4. 重命名新列

顺序 GUID

The answer https://stackoverflow.com/questions/11974939/adding-a-uniqueidentifier-column-and-adding-the-default-to-generate-new-guid来自“Icarus”的 ALTER TABLE 语句使用newsequentialid()根据您的声明生成顺序 GUID:

我希望它是一个顺序递增的Guid。

ALTER TABLE your_table
    ADD your_column UNIQUEIDENTIFIER DEFAULT newsequentialid() NOT null

请注意“Icarus”答案评论部分中“Johan”的隐私问题:

如果担心隐私,请勿使用newsequentialid()。可以猜测下一个生成的 GUID 的值,从而访问与该 GUID 关联的数据

更改主键

您要更改的列是 ID 列,并且您已将其设置为主键。因此,在删除现有 ID 列之前,您需要使用另一个删除主键ALTER TABLESQL 命令。

查看所选的answer https://stackoverflow.com/questions/8761570/how-can-i-alter-a-primary-key-constraint-using-sql-syntax来自“darnir”的“如何使用 SQL 语法更改主键约束?”

ALTER TABLE <Table_Name>
DROP CONSTRAINT <constraint_name>

ALTER TABLE <Table_Name>
ADD CONSTRAINT <constraint_name> PRIMARY KEY (<Column1>,<Column2>)

请参阅“Oleg”的注释以确定这是否是一个因素:

PRIMARY KEY CONSTRAINT 无法更改,您只能删除它并重新创建。对于大数据集,它可能会导致较长的运行时间,从而导致表不可用。

当命令使用时我遇到了问题DROP CONSTRAINT以上已执行。结果窗格列出了自动生成的约束,即使我在ALTER TABLE ... ADD COLUMN命令。看到这个question https://stackoverflow.com/questions/7663390/why-does-sql-keep-creating-a-df-constraint“为什么 SQL 不断创建 DF 约束?”和这个question https://stackoverflow.com/questions/19460912/the-object-df-is-dependent-on-column-changing-int-to-double如果你经历过类似的事情。

为了解决删除约束的问题,我使用了“ScubaSteve”的答案question https://stackoverflow.com/questions/1430456/how-to-drop-sql-default-constraint-without-knowing-its-name:“如何在不知道其名称的情况下删除 SQL 默认约束?”添加“Seven”注释后,以下是 SQL 命令:

DECLARE @ObjectName NVARCHAR(100)
SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
IF @ObjectName IS NOT NULL EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + @ObjectName)

“ScubaSteve 的回答”中“七”的评论。我添加了“if”条件,因为有时当未找到约束时 EXEC 会失败。

要使此脚本具有幂等性,请添加IF @ObjectName IS NOT NULL在 EXEC 命令之前

最终的解决方案

确保更换MyTableName, MyColumnName, and dbo在下面的代码中添加到您的表名称、列名称(例如,将列名称设置为Id)和表模式分别。

public override void Up()
{
    Sql(@"
        DECLARE @ObjectName NVARCHAR(100)
        SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
        WHERE [object_id] = OBJECT_ID('[dbo].[MyTableName]') AND [name] = 'MyColumnName';
        IF @ObjectName IS NOT NULL EXEC('ALTER TABLE [dbo].[MyTableName] DROP CONSTRAINT ' + @ObjectName)

        ALTER TABLE dbo.MyTableName DROP CONSTRAINT PK_MyTableName, COLUMN MyColumnName

        ALTER TABLE dbo.MyTableName
        ADD Id UNIQUEIDENTIFIER DEFAULT (newsequentialid()) NOT NULL
        CONSTRAINT PK_MyTableName
        PRIMARY KEY CLUSTERED ([MyColumnName])
    ");
}

public override void Down()
{
    Sql(@"
        DECLARE @ObjectName NVARCHAR(100)
        SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
        WHERE [object_id] = OBJECT_ID('[dbo].[MyTableName]') AND [name] = 'MyColumnName';
        IF @ObjectName IS NOT NULL EXEC('ALTER TABLE [dbo].[MyTableName] DROP CONSTRAINT ' + @ObjectName)

        ALTER TABLE dbo.MyTableName DROP CONSTRAINT PK_MyTableName, COLUMN Id

        ALTER TABLE MyTableName
        ADD MyColumnName int IDENTITY(1, 1) NOT NULL
        CONSTRAINT PK_MyTableName
        PRIMARY KEY CLUSTERED ([MyColumnName] ASC)        
    ");
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Code First 从 int 迁移到 Guid 主键问题 的相关文章

  • 使用Unity时实体框架错误

    在尝试解决我的服务类时 我收到一个错误DbContext无法构造 因为它是一个抽象类 错误消息在这里 Unity Exceptions ResolutionFailedException Resolution of the dependen
  • 将复合外键映射到复合主键,其中外键也是主键

    我想将 VM hostname datetime 和 name 属性设置为复合键磁盘类 同时VM hostname和datetime磁盘类应参考 VM hostname 和 datetime虚拟机类 即外键 我这样做了 但它给了我这个例外
  • Asp.Net Core:将数据添加到IdentityDbContext或使用DbContext

    我与Asp Net Core WebApi项目 我可以将我的表格添加到身份数据库上下文 像这样 public class ApplicationDbContext IdentityDbContext
  • 实体框架从 saveChanges 中的上下文获取用户

    我的解决方案中有两个项目 UI 作为 mvc 和首先用于实体模型代码的类项目 我的模型中有多个实体 但现在我需要通过新的审计字段来扩展它们 我需要保存谁更改了实体 我添加了新界面 public interface IAuditable
  • 实体框架:跳过/接受功能

    我只是好奇 Skip 和 Take 函数如何在 Entity Framework 中工作 使用 EF 6 1 If I do db Events OrderByDescending x gt x Date Take maxPageSize
  • 更改 EF6 源代码以将短值转换为布尔值

    修改映射代码来转换a的可行性是什么 short如果布尔目标属性在 POCO 模型中用属性标记 则值为零或非零到 false 或 true 我的意思是 这应该是 EF 开源的优点之一 并且仅供内部使用 任何有关我在代码中查找位置的提示将不胜感
  • 合并实体框架中的迁移条目

    我有一个 Entity Framework 6 CF 项目 其中已经进行了一些迁移 该模型现已稳定 无需保留已存在的迁移历史记录 有没有办法重置模型并将所有迁移命令合并到初始迁移中 例如 第一次迁移添加一列 而第二次迁移添加唯一的非聚集索引
  • 有没有办法用 Moq 来一般模拟 DbSet.Find 方法?

    我目前正在使用扩展方法来将 DbSets 一般模拟为列表 public static DbSet
  • project.Models.tableName:字段pvid必须是字符串或数组类型,最大长度为'20'

    当我尝试使用以下命令在数据库中添加新条目时 遇到以下异常错误 db patient visit Add pv db SaveChanges project dll 中发生 System InvalidOperationException 类
  • 实体框架删除具有外键关系的实体时出错

    由于外键关系 我在删除某些实体时遇到问题 我理解以下错误消息 并已尽我所能想到删除实体而不会出现此错误 DELETE 语句与 REFERENCE 约束冲突 FK QuizUserAnswer QuizWithQuestion 冲突发生在 数
  • 重命名 Identity 表并导致 EF6 迁移失败

    我正在尝试通过 EF6 Package Manager 中的迁移工具重命名我的 Identity 2 0 表 然而 它已经炸毁了一部分 我只是在 IdentityModels cs 中的 ApplicationDBContext Creat
  • ProviderManifestToken 2008 或 2012

    应用程序 NET 4 5 C 使用 EF6 和数据库优先方法 支持 SQL Server 2008R2 2012 和 2014 这个问题是关于ProviderManifestToken自动生成的 edmx 文件的属性 根据使用哪个版本的数据
  • 在实体框架中映射自定义数据库值函数

    我有一个简单的数据库函数 它需要两个字符串作为参数并返回一个字符串 我想用实体框架来映射它 如同这个问题 https stackoverflow com questions 45451383 dbfunction cannot be tra
  • EF数据库首先如何针对数据库更改更新模型?

    在班级图书馆Ado net Entity Data Model已生成 POCO 类 这些是第一次生成的 但数据库更改并未得到反映 在edmx图表右键单击并选择Update Model from Database显示新创建的表 但即使选择添加
  • EF6 Code First 支持表值函数吗?

    是否可以在 EF6 Code First 中调用 TVF 我首先使用 EF6 数据库启动了一个新项目 EF 能够将 TVF 导入到模型中并调用它就好了 但是 对于我一直在处理的没有 RI 的大型只读数据库 更新模型变得非常耗时并且存在问题
  • 使用 EF6 连接到 SQL Server

    在 EF5 之前 为了连接到 SQL Server 2012 我所需要做的就是指定一个如下所示的连接字符串 Data Source SqlExpress Initial Catalog MyDatabase Integrated secur
  • Entity Framework 6(代码优先)实体版本控制和审计

    我正在考虑将 Entity Framework 6 1 1 与 SQL Server 2008 R2 一起使用 目前 我正在使用代码优先的 EF 功能创建模型和数据库 我的基本用例是创建一个特定实体的所有更改的日志 ID是关键栏 以帮助审核
  • 任何 ToList() 的 EF6 NullReferenceException

    使用 C NET 4 5 2 Entity Framework 6 1 3 和 System Linq 我遇到了一个令人困惑的异常 异常本身似乎不包含有用的信息来确定引发该异常的原因 执行以下代码行会导致 NullReferenceExce
  • EF6 不从数据库生成外键关联

    PROBLEM 我正在尝试使用数据库优先方法创建 EF6 模型 简单来说 我有2张桌子tblUser and tblMilkMan上有外键关系UserID柱子 但是当我创建一个新的 EDMX 图并添加 2 个表时 我看不到其中的关系 未创建
  • 如何检查DBContext是否已释放?

    我想与从外部 继承类 调用的另一个方法共享数据库上下文 而不创建新的上下文 除非正在释放它 我想检查上下文是否已处理 以便我可以创建新的上下文 这是休息 api 有多个实体的批量上传 我想共享事务 因此如果一个实体失败 它将不会提交到数据库

随机推荐