如何通过EF迁移将int ID列更改为Guid?
我正在使用EF代码优先方法,并希望将Id
字段更改为guid
但似乎无法通过以下错误。
这是我的第一次迁移:
public partial class CreateDownloadToken : DbMigration { public override void Up() { CreateTable( "dbo.DownloadTokens", c => new { Id = c.Int(nullable: false, identity: true), FileId = c.Int(), UserId = c.String(nullable: false, maxLength: 128), ValidUntil = c.DateTime(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.Files", t => t.FileId) .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) .Index(t => t.FileId) .Index(t => t.UserId); } public override void Down() { DropForeignKey("dbo.DownloadTokens", "UserId", "dbo.Users"); DropForeignKey("dbo.DownloadTokens", "FileId", "dbo.Files"); DropIndex("dbo.DownloadTokens", new[] { "UserId" }); DropIndex("dbo.DownloadTokens", new[] { "FileId" }); DropTable("dbo.DownloadTokens"); } }
后来我意识到我需要我的Id
列是GUID所以我改变了我的模型文件:
public class DownloadToken { [Key, DatabaseGenerated(DatabaseGeneratedOption.Computed)] public Guid Id { get; set; } public int? FileId { get; set; } [ForeignKey("FileId")] public virtual File File { get; set; } [Required] public string UserId { get; set; } [ForeignKey("UserId")] public virtual User User { get; set; } [Required] public DateTime ValidUntil { get; set; } }
运行Add-Migration ChangeDownloadTokenIdToGuid
它会生成以下文件:
public partial class ChangeDownloadTokenIdToGuid : DbMigration { public override void Up() { DropPrimaryKey("dbo.DownloadTokens"); AlterColumn("dbo.DownloadTokens", "Id", c => c.Guid(nullable: false)); AddPrimaryKey("dbo.DownloadTokens", "Id"); } public override void Down() { DropPrimaryKey("dbo.DownloadTokens"); AlterColumn("dbo.DownloadTokens", "Id", c => c.Int(nullable: false, identity: true)); AddPrimaryKey("dbo.DownloadTokens", "Id"); } }
使用Update-Database
运行此文件会导致此错误:
Identity column 'Id' must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable.
任何想法为什么会这样?
这是因为无法将之前的int
类型的Id
列转换为Guid
类型(正是尝试执行AlterColumn
方法)。 此外,错误消息建议您,新类型的Id
列可以是set中的类型之一: int,bigint,smallint,tinyint,或者小数或数字,其比例为0 ,对于它们,可以从int
执行转换类型。
解决方案 – 只需删除Id
列,然后使用新的Guid
类型重新创建它,以这种方式更改迁移:
public partial class ChangeDownloadTokenIdToGuid : DbMigration { public override void Up() { DropPrimaryKey("dbo.DownloadTokens"); DropColumn("dbo.DownloadTokens", "Id"); AddColumn("dbo.DownloadTokens", "Id", c => c.Guid(nullable: false, identity: true)); AddPrimaryKey("dbo.DownloadTokens", "Id"); } public override void Down() { DropPrimaryKey("dbo.DownloadTokens"); DropColumn("dbo.DownloadTokens", "Id"); AddColumn("dbo.DownloadTokens", "Id", c => c.Int(nullable: false, identity: true)); AddPrimaryKey("dbo.DownloadTokens", "Id"); } }
PS为什么使用
DatabaseGeneratedOption.Computed
属性,而不是DatabaseGeneratedOption.Identity
?
即使Slava Utesinov的作品,它只适用于空表或没有其他表指的是您正在转换的表。 因此,这个答案将帮助那些以更复杂的数据库设置结束此页面的人。
下面是一个可以在迁移类中使用的实用程序函数,应该可以从Up / Down函数调用它。 该函数还处理表引用您尝试从Int转换为Guid的表。 此辅助函数假定您要转换的列称为“Id”,但应该是相当通用的。
public void Convert(bool toGuid, string parent, params string[] children) { if (toGuid) { AddColumn($"dbo.{parent}s", "Id2", c => c.Guid(nullable: false, identity: true, defaultValueSql: "newid()")); } else { AddColumn($"dbo.{parent}s", "Id2", c => c.Int(nullable: false, identity: true)); } foreach (var child in children) { DropForeignKey($"dbo.{child}s", $"{parent}_Id", $"dbo.{parent}s"); DropIndex($"dbo.{child}s", new[] { $"{parent}_Id" }); RenameColumn($"dbo.{child}s", $"{parent}_Id", $"old_{parent}_Id"); if (toGuid) { AddColumn($"dbo.{child}s", $"{parent}_Id", c => c.Guid()); } else { AddColumn($"dbo.{child}s", $"{parent}_Id", c => c.Int()); } Sql($"update c set {parent}_Id=p.Id2 from {child}sc inner join {parent}sp on p.Id=c.old_{parent}_Id"); DropColumn($"dbo.{child}s", $"old_{parent}_Id"); } DropPrimaryKey($"dbo.{parent}s"); DropColumn($"dbo.{parent}s", "Id"); RenameColumn($"dbo.{parent}s", "Id2", "Id"); AddPrimaryKey($"dbo.{parent}s", "Id"); foreach (var child in children) { CreateIndex($"dbo.{child}s", $"{parent}_Id"); AddForeignKey($"dbo.{child}s", $"{parent}_Id", $"dbo.{parent}s", "Id"); } }
因此,在您的情况下,您的向上/向下function将是:
上述就是C#学习教程:如何通过EF迁移将int ID列更改为Guid?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public override void Up() { Convert(true,"DownloadToken"); } public override void Down() { Convert(false, "DownloadToken"); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/987841.html