【问题标题】:ASP.NET Identity How to I add a required property for a custom ApplicationUser?ASP.NET Identity 如何为自定义 ApplicationUser 添加必需的属性?
【发布时间】:2013-11-18 00:59:51
【问题描述】:

我正在尝试为 ApplicationUser (ASP.NET Identity, MVC5) 添加一个必需的属性

这是一个简单的例子:

public class ApplicationUser : IdentityUser
{
    [Required]
    public string FirstName { get; set; }
}

该字段在数据库中创建,但最终 NULLABLE
我希望该字段不为空。

知道如何解决这个问题吗?

【问题讨论】:

  • 这很难说。因此,您在表单上定义了该字段,并且该表单已提交?您是以 AJAX 还是标准回发的形式发送数据?是所有字段都是空白的还是只有一个?
  • 谢谢。我不是在处理前端(没关系)。我需要数据库来创建一个 NOT NULL 字段。使用 [Required] 时这是预期的
  • 这是一个很好的例子,我希望很多人都在尝试做类似的事情。 应该可以只存储扩展的 ApplicationUser 实体而不存储单独的 IdentityUser 实体。
  • 我有一个类似的问题——试图向 ApplicationUser 添加一个 bool 属性,但我不在乎它是否可以为空。当我添加属性并运行更新数据库时,我收到错误消息:“'ApplicationUser' 上的 'ShowCompleted' 属性无法设置为 'null' 值。您必须将此属性设置为类型的非 null 值'System.Boolean'。”
  • @Number8 看起来很奇怪,因为这几乎与我们遇到的相反。您是否尝试过明确地将其设为可为空的布尔值? (即 bool?ShowCompleted)

标签: asp.net entity-framework asp.net-mvc-5 asp.net-identity


【解决方案1】:

这更像是对上面@Number8 的评论(目前不允许评论)。 我遇到了同样的问题,这可能与 OP 的问题有关。数据库更新检查迁移的配置类 (Configuration.cs)。如果你有一个种子方法,你需要在你的种子方法中为非空属性设置默认值(或者让它们在模型中可以为空)。

【讨论】:

    【解决方案2】:

    我可以通过将以下行添加到 configuration.cs 文件中的种子方法来使此类字段不为空

    context.Database.ExecuteSqlCommand("ALTER TABLE [AspNetUsers] ALTER COLUMN [FirstName] nvarchar(MAX) NOT NULL");

    【讨论】:

      【解决方案3】:

      通过结合herehere 的答案找到了一种方法

      最终的解决方案对我来说真的违反直觉。
      您似乎需要为 ApplicationUser 显式设置一个单独的表名
      此外,您必须确保 first
      调用 base.OnModelCreating(modelBuilder) 如果您不这样做,该字段将永远不会遵守 [Required] 属性的 NOT NULL 方面。

      这是我使用的代码,它最终可以正常工作:

      public class ApplicationUser : IdentityUser
      {
          public string FirstName { get; set; }
      }
      
      public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
      {
          protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {
              base.OnModelCreating(modelBuilder);
              //modelBuilder.Entity<IdentityUser>().ToTable("Users"); // Won't work if the table name is the same.
              modelBuilder.Entity<ApplicationUser>().ToTable("Users")
                  .Property(p => p.FirstName).IsRequired();
          }
          // etc.
      }
      

      这导致以下数据库结构:

      【讨论】:

      • 我个人不太喜欢这个解决方案,因为它会拆分用户表。将这个问题留待一段时间,看看是否有更直观的答案。
      • 您的最后一个解决方案对我不起作用。生成的导致错误的 SQL 语句。如您所见,AspNetUsers 已重命名并正在添加 FK。
      【解决方案4】:

      按层次结构表 (TPH) 映射是 Entity Framework Code First 中的默认设置。这意味着如果共享同一个表的类型层次结构中的所有类都不需要 FirstName,则该列不能为非空。

      如果您希望 FirstName 列不可为空,您可以选择不同的映射策略。如果您改用按类型表 (TPT),那么您将拥有一个用于 IdentityUser(默认为 AspNetUsers)的表和另一个用于 ApplicationUser 的表。 由于 FirstName 现在对于 ApplicationUser 表是唯一的,因此它可以是不可为空的。

      要使用 TPT,您可以像这样覆盖 OnModelCreating 方法:

      protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
      {
          base.OnModelCreating(modelBuilder);
          modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUser");
      }
      

      【讨论】:

      • 是的,这就是我必须做的。这似乎真的违反直觉,特别是因为扩展 ApplicationUser 是 ASP.NET Identity 的核心部分,你会认为会有一些官方的方法来解决这个问题。
      • 当我尝试执行此操作时,运行“update-database -force”时出现此错误:“外键 'FK_dbo.ApplicationUser_dbo.AspNetUsers_Id' 引用无效表 'dbo.AspNetUsers'。”
      • 如何防止创建代表 IdentityUser 的父用户表?
      【解决方案5】:

      我尝试使用 Required 属性在 IdentityUser 中添加一个不可为空的字符串字段,并覆盖 OnModelCreating 方法,如下所示:

      protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
      {
          modelBuilder.Entity<ApplicationUser>().Property(x => x.FirstName).IsRequired();
      
          base.OnModelCreating(modelBuilder);
      }
      

      两者都没有成功。我不知道这是设计使然,还是新的 ASP.NET 标识中的错误。我还搜索了与错误相关但没有成功。

      也许添加迁移可以帮助您实现目前所需的功能。

      【讨论】:

      • 有一种无需单独迁移即可解决此问题的方法,但效果不是很好。
      猜你喜欢
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2015-11-03
      • 2014-07-03
      • 1970-01-01
      相关资源
      最近更新 更多