为什么ASP.NET标识接口使用字符串作为主键和外键?
我首先查看新ASP.NET标识类上的接口以及它使用实体框架代码创建的数据库。我正在使用Visual Studio 2013 RC 乍一看,数据库架构看起来相当正常: 但是所有的键都是NVARCHAR(128) 出于某种疯狂的原因,为什么ASP.NET标识接口使用字符串作为主键和外键?,asp.net,asp.net-identity,Asp.net,Asp.net Identity,我首先查看新ASP.NET标识类上的接口以及它使用实体框架代码创建的数据库。我正在使用Visual Studio 2013 RC 乍一看,数据库架构看起来相当正常: 但是所有的键都是NVARCHAR(128) 出于某种疯狂的原因,AspNetUserSecrets.Id是一个PK,看起来它可以指向AspNetUsers表中的多个记录。这是否意味着多个aspnetuser必须共享同一密码 当我看到你被迫实现的接口时,这些都是字符串 public class User : IUser {
AspNetUserSecrets.Id
是一个PK,看起来它可以指向AspNetUsers
表中的多个记录。这是否意味着多个aspnetuser
必须共享同一密码
当我看到你被迫实现的接口时,这些都是字符串
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)字段的文章:
目的是允许两种任意id类型(即
int
、guid
、字符串
),但也避免id属性出现序列化/强制转换问题
因此,您可以随意定义密钥,只需实现接口方法即可
public class MyUser : IUser {
public int Id { get; set; }
string IUser.Id { get { return Id.ToString(); } }
}
此外,郝说:
使用ASP.NET Core,您可以用一种非常简单的方法为Identity的模型指定所需的数据类型 第一步,将标识类从
公共类应用程序用户:IdentityUser
{
}
公共类应用程序角色:IdentityRole
{
}
使用类和所需的数据类型声明数据库上下文:
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);
}
}
public类ApplicationDbContext:IdentityDbContext
{
公共应用程序DBContext(DbContextOptions选项)
:基本(选项)
{
}
模型创建时受保护的覆盖无效(ModelBuilder)
{
基于模型创建(生成器);
//自定义ASP.NET标识模型,并根据需要覆盖默认值。
//例如,可以重命名ASP.NET标识表名称等。
//在调用base.OnModelCreating(builder)后添加自定义项;
}
}
在startup类中,使用模型声明identity service,并声明主键所需的数据类型:
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders();
services.AddIdentity()
.AddEntityFrameworkStores()
.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();
}
[HttpGet]
公共异步任务测试()
{
ApplicationUser=await\u userManager.GetUserAsync(HttpContext.user);
Guid userId=user.Id;//不从字符串强制转换,它是Guid数据类型
抛出新的NotImplementedException();
}
您正在使用测试版。最终版本与我的理解不同。我听说他们已经完全删除了AspNetUserSecrets表。这将解决其中一个问题:)但我仍然不明白为什么所有的密钥都是NVARCHER(128)…很抱歉,因为答案是由内部人员提供的,我早就应该将其标记为正确的。为什么如果这是将id用作int所需的唯一代码,我们有这样的InEnumerable
:到处都是?从Identity的角度来看,这就是所有需要的,将会有一系列相应的应用程序代码更改。总的来说,这是相当令人难以接受的,我们已经在Identity V3中尝试过简化这一点。我想要简单的生活,但CodePlex没有Identity 3.0的路线图。因此,你能给我们一个大概的日期吗?如果您在显式接口声明中得到“'IUser.Id'不是接口的成员”,那么将上述代码更改为:string IUser.Id{get{return Id.ToString();}}
c#也可以根据返回类型实现不同的方法签名。由于这是一个限制,microsoft不能创建Identity.EntityFramework.Int包、GuiD包和所有选项吗?@Rick为什么是nvarchar(128)而不是uniqueidentifier?官方文档中有一篇文章回答了这个问题:如果我不想定义角色,我们将通过ACL处理角色。
[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();
}