为什么ASP.NET Identity接口使用字符串作为主键和外键?

时间:2013-10-08 03:33:26

标签: asp.net asp.net-identity

我正在查看新ASP.NET Identity类的接口以及它使用Entity Framework Code First创建的数据库。我正在使用Visual Studio 2013 RC。

乍一看,数据库架构看起来相当正常:

enter image description here

但所有密钥都是NVARCHAR(128)

出于某些疯狂的原因,AspNetUserSecrets.Id是一个PK,看起来它可能指向AspNetUsers表中的多个记录。这是否意味着多个AspNetUsers必须共享相同的密码?

当我看到你要强制实现的接口时,这些都是字符串......

public class User : IUser
{
    public string Id { get; set; }
    public string UserName { get; set; }
}

public class UserSecret : IUserSecret
{
    public string UserName { get; set; }
    public string Secret { get; set; }
}

public class UserRole : IUserRole
{
    public string UserId { get; set; }
    public string RoleId { get; set; }
}

public class UserClaim : IUserClaim
{
    public string UserId { get; set; }
    public string ClaimType { get; set; }
    public string ClaimValue { get; set; }
}

public class UserManagement : IUserManagement
{
    public string UserId { get; set; }
    public bool DisableSignIn { get; set; }
    public DateTime LastSignInTimeUtc { get; set; }
}

public class Tokens : IToken
{
    public string Id { get; set; }
    public string Value { get; set; }
    public DateTime ValidUntilUtc { get; set; }
}

public class UserLogin : IUserLogin
{
    public string UserId { get; set; }
    public string LoginProvider { get; set; }
    public string ProviderKey { get; set; }
}

public class Role : IRole
{
    public string Id { get; set; }
    public string Name { get; set; }
}

所以我接受这样一个事实,即我可能必须使用字符串来实现PK和FK关系。

但我真的很想知道它为什么这样建造......?

编辑:时间已过,现在有关于如何扩展asp.net标识以使用int(或guid)字段的文章:

http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

3 个答案:

答案 0 :(得分:31)

目的是允许两种任意ID类型(即intguidstring),同时避免对id属性进行序列化/转换问题。

因此,您可以根据需要定义密钥,只需实现接口方法

public class MyUser : IUser {
  public int Id { get; set; }
  string IUser.Id { get { return Id.ToString(); } }
}

答案 1 :(得分:17)

添加郝说:

  1. Identity运行时更喜欢用户ID的字符串,因为我们不希望在确定用户ID的正确序列化(我们也因为同样的原因使用字符串索引),例如,所有(或大多数)Identity接口都将用户ID称为字符串。
  2. 自定义持久层的人,例如实体类型,可以选择他们想要的任何类型的键,但然后他们自己提供键的字符串表示。
  3. 默认情况下,我们为每个新用户使用GUID的字符串表示,但这只是因为它为我们提供了一种非常简单的方法来自动生成唯一ID。

答案 2 :(得分:2)

使用ASP.NET Core,您可以通过一种非常简单的方式为Identity的模型指定所需的数据类型。

第一步,覆盖<中的身份类字符串> <您想要的数据类型>

public class ApplicationUser : IdentityUser<Guid>
{
}

public class ApplicationRole : IdentityRole<Guid>
{
}

使用您想要的类和数据类型声明您的数据库上下文:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            // Customize the ASP.NET Identity model and override the defaults if needed.
            // For example, you can rename the ASP.NET Identity table names and more.
            // Add your customizations after calling base.OnModelCreating(builder);
        }
    }

在您的启动类中,使用您的模型声明身份服务并声明主键所需的数据类型:

services.AddIdentity<ApplicationUser, ApplicationRole>()
            .AddEntityFrameworkStores<ApplicationDbContext, Guid>()
            .AddDefaultTokenProviders();

在ASP.NET身份表中,主键仍然在NVARCHAR中,但在您的应用程序中,它将是您想要的数据类型。 您可以在控制器中检查:

    [HttpGet]
    public async Task<IActionResult> Test()
    {
        ApplicationUser user = await _userManager.GetUserAsync(HttpContext.User);
        Guid userId = user.Id; // No cast from string, it's a Guid data type
        throw new NotImplementedException();
    }