[英]UserManager.CreateAsync does not save added properties in ApplicationUser
[英]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 设计器
如果您将此处的 UserId 字段更改为 uniqueIdentifier,它将级联并更改其他表中的数据类型,一直回到 AspNetUsers。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.