繁体   English   中英

UserManager.CreateAsync 不生成 Id

[英]UserManager.CreateAsync does not generate Id

我刚刚将我的 MVC 5 应用程序(以前是带有SimpleMembership MVC 3)升级到 ASP.NET Identity 2.0,我可以与现有用户一起工作,但是当我执行以下操作来创建一个新用户时:

var user = new ApplicationUser();
//user.Id = db.Users.Max(u => u.Id) + 1;    //does not help
user.UserName = model.UserName;
user.Email = model.EMailAddress;
var result = await UserManager.CreateAsync(user, model.Password);

我得到以下信息:

System.Data.Entity.Core.UpdateException:更新条目时出错。 有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException: 无法将值 NULL 插入到列“Id”、表“MyDB.dbo.AspNetUsers”中; 列不允许空值。 插入失败。 该语句已终止。

有谁知道为什么会这样?

这是我的UserManager

var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get<MyDbContext>()));

manager.UserValidator = new UserValidator<ApplicationUser, int>(manager)
{
    AllowOnlyAlphanumericUserNames = false,
    RequireUniqueEmail = true
};

manager.PasswordValidator = new PasswordValidator
{
    RequiredLength = 6,
    RequireNonLetterOrDigit = false,
    RequireDigit = false,
    RequireLowercase = false,
    RequireUppercase = false,
};

manager.EmailService = new EmailService();

var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
    manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, int>(dataProtectionProvider.Create("ASP.NET Identity"));
}

我对用户和角色使用int键,但我之前有默认的string -keys 并且那里Id也没有填充,我得到了类似的错误。

我发现了问题:
因为我将键从string更改为int所以创建了以下迁移:

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

在那里它正确生成了identity: true ,但是 MSSQL 无法将现有列转换为标识列 => 该列变成了“普通的INT列”。
Identity 然后必须假设该列是一个身份列并插入null作为键,并期望 DB 生成 id => 异常。

解决方案是从旧备份恢复到我的SimpleMembership数据库,并在创建AspNetUsers表时使用int键直接将其转换为ASP.NET Identity

PS:但我仍然不知道为什么我在string -keys 上遇到了类似的问题,但无论如何我更喜欢int -keys ......

刚刚遇到这个问题,我并没有立即清楚在保持迁移的同时如何解决它,所以我添加了这个答案作为对@ChrFin 在他的评论中提到的内容的进一步澄清。

如果您通过迁移从Guid切换到Int Id,这就是您必须在给定迁移中修改以创建UserManager.Create()不会失败的表的内容:

//AlterColumn("dbo.AspNetRoles", "Id", c => c.Int(nullable: false, identity: true));
DropColumn("dbo.AspNetRoles", "Id");
AddColumn("dbo.AspNetRoles", "Id", c => c.Int(nullable: false, identity: true));

// ...

//AlterColumn("dbo.AspNetUsers", "Id", c => c.Int(nullable: false, identity: true));
DropColumn("dbo.AspNetUsers", "Id");
AddColumn("dbo.AspNetUsers", "Id", c => c.Int(nullable: false, identity: true));

有关所需更正的其他信息,以回答评论:

这些修改包含在自动生成的迁移文件的Up()方法中。 基本上,如果你有这个问题,你应该能够找到注释行AlterColumn("dbo.AspNetRoles", "Id", c => c.Int(nullable: false, identity: true)); (或其等价物),如果您在您的解决方案中搜索它。

迁移文件的Up()方法也会包含其他行/操作,但它们可以保持原样,只需要覆盖以上两个。

我实际上有一段时间没有使用 ASP.NET MVC(切换到 Core),但据我Updade-Database ,可以使用包管理器命令行中的Updade-Database命令执行迁移。

但是,当然,首先您必须回滚上次迁移(未修改的迁移,导致问题)。 据我Update-Database -TargetMigration:"migration_name" ,回滚到以前的迁移是使用Update-Database -TargetMigration:"migration_name"命令完成的,其中migration_name是前面的名称,仍然是好的迁移。

从 Guid(随机字符串)切换到 int Id 后,我遇到了同样的问题,但我能够以不同的方式解决它。 我能够使用 SQL Server 对象资源管理器 (SSOE)。 我打开 SSOE,找到我的数据库并展开表,然后右键单击 dbo.AspNetUsers > View Designer。 我看到 Id 是一个 int,我认为这是正确的,但实际上它应该是 uniqueIdentifier。 我试图将数据类型更改为 uniqueIdentifier 但不能。 当我单击“更新”失败时,它给了我一条错误消息,说明它在其他表中被引用为外键。 它列出了我认为的 3 个表,如果您按照路径进行操作,它会指向表dbo.AspNetUserClaims aspNetUserClaims 设计器

aspNetUserClaims 设计器

如果您将此处的 UserId 字段更改为 uniqueIdentifier,它将级联并更改其他表中的数据类型,一直回到 AspNetUsers。

aspNetUserClaims uniqueIdentifier

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM