【问题标题】:UserManager.CreateAsync does not generate IdUserManager.CreateAsync 不生成 Id
【发布时间】:2014-08-07 23:27:26
【问题描述】:

我刚刚将我的 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-键,Id 也没有填充,我得到了类似的错误。

【问题讨论】:

  • 你的ApplicationUser类是什么样的?
  • @DavidG: public class ApplicationUser : IdentityUser&lt;int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim&gt; - 所有Application*-classes 都有int-key 和一些自定义属性。

标签: c# asp.net-mvc entity-framework asp.net-identity-2


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 由于您的发现,我删除了 Migrations 文件并删除了表并运行了 Update-Database,它起作用了。
  • 您有使用 sql 来更新列的解决方案吗?我在实时服务器上运行它,丢弃不是一个选项..
  • dropping is not an option - 但它是唯一的。但是您可以创建一个新列,然后只删除旧列而不是整个表...
【解决方案2】:

刚刚遇到这个问题,我并不清楚在保持迁移的同时如何解决它,所以我添加这个答案作为对@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 =&gt; c.Int(nullable: false, identity: true));(或其等效项)。

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

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

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

【讨论】:

  • 我认为这是我需要做的。这些是否进入 up 方法?修改后如何运行?
  • @SendETHToThisAddress 抱歉,我的回复太长,无法作为评论发送,所以我将其添加到答案的末尾。 :) 我希望它能澄清它。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2020-03-16
    • 2012-11-19
    • 2015-07-09
    • 1970-01-01
    • 2012-02-22
    • 2011-01-11
    相关资源
    最近更新 更多