当前位置: 首页 > 知识库问答 >
问题:

如何在Microsoft中更改id的类型。AspNet。身份实体框架。标识符

糜单弓
2023-03-14

(ASP.NET MVC 5、EF6、VS2013)

我正在尝试弄清楚如何将“Id”字段的类型从字符串更改为类型中的int:

Microsoft.AspNet.Identity.EntityFramework.IdentityUser

为了使新用户帐户与整数ID而不是GUID相关联。但这似乎比在派生的用户类中简单地添加int类型的新Id属性要复杂得多。看看这个方法签名:

(来自程序集Microsoft.AspNet.Identity.Core.dll)

public class UserManager<TUser> : IDisposable where TUser : global::Microsoft.AspNet.Identity.IUser
  {
  ...
  public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
  ...
  }

因此,似乎还有其他方法烘焙到ASP中。NET identity framework,要求用户ID为字符串。我也需要重新实现这些类吗?

解释为什么我不想在用户表中存储ID的GUID:

-会有其他表通过外键将数据与用户表联系起来。(当用户在网站上保存内容时。)我认为没有理由使用更大的字段类型并花费额外的数据库空间而没有明显的优势。(我知道还有其他关于使用GUID与int id的帖子,但似乎许多人建议int id更快,使用更少的空间,这仍然让我感到困惑。)

-我计划公开一个restfulendpoint,以允许用户检索有关特定用户的数据。我想:

/users/123/name

比…干净

/users/{af54c891-69ba-4ddf-8cb6-00d368e58d77}/name

有人知道为什么ASP。NET团队决定以这种方式实现IDs?我把它改成int类型是不是目光短浅?(也许我缺少了一些好处。)

谢谢

-本

共有3个答案

伍耀
2023-03-14

@HaoKung

我成功地用你的夜间版本制作了int-id。使用者身份GetUserId()问题仍然存在,但我现在只做了int.parse()。

最大的惊喜是,我不需要自己创建ID,db是用身份ID制作的,它是自动为新用户设置的。。。

型号:

    public class ApplicationUser : IdentityUser<int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public ApplicationUser()
    {
    }
    public ApplicationUser(string name) : this() { UserName = name; }
}

public class ApplicationDbContext : IntUserContext
{
    public ApplicationDbContext()
    {

    }
}

private class IntRole : IdentityRole<int, IntUserRole>
{
    public IntRole()
    {
    }
    public IntRole(string name) : this() { Name = name; }
}
private class IntUserRole : IdentityUserRole<int> { }
private class IntUserClaim : IdentityUserClaim<int> { }
private class IntUserLogin : IdentityUserLogin<int> { }
private class IntUserContext : IdentityDbContext<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public IntUserContext()
        : base("DefaultConnection")
    {

    }
}
private class IntUserStore : UserStore<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public IntUserStore(DbContext context)
        : base(context)
    {

    }
}
private class IntRoleStore : RoleStore<IntRole, int, IntUserRole>
{
    public IntRoleStore(DbContext context)
        : base(context)
    {
    }
}

控制器:

        public AccountController()
        : this(new UserManager<ApplicationUser, int>(new IntUserStore(new ApplicationDbContext())))
    {
    }

    public AccountController(UserManager<ApplicationUser, int> userManager)
    {
        UserManager = userManager;
    }

    public UserManager<ApplicationUser, int> UserManager { get; private set; }

希望发布版本很快就会到来:D。。。

P、 美国不能写评论,所以我做了一个回答,对不起。

孙才捷
2023-03-14

因此,如果您想要int id,您需要创建自己的POCO IUser类并在1.0 RTM版本中为您的自定义IUser类实现您的IUserStore。

这是我们没有时间支持的,但是我现在正在研究在1.1中使其变得简单。希望很快在夜间构建中会有一些可用的东西。

使用1.1-alpha1示例更新:如何获得夜间构建

如果您更新到最新的夜间位,您可以试用新的1.1-alpha1 API,这将使现在的操作更容易:例如,插入guid而不是字符串应该是这样的

    public class GuidRole : IdentityRole<Guid, GuidUserRole> { 
        public GuidRole() {
            Id = Guid.NewGuid();
        }
        public GuidRole(string name) : this() { Name = name; }
    }
    public class GuidUserRole : IdentityUserRole<Guid> { }
    public class GuidUserClaim : IdentityUserClaim<Guid> { }
    public class GuidUserLogin : IdentityUserLogin<Guid> { }

    public class GuidUser : IdentityUser<Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
        public GuidUser() {
            Id = Guid.NewGuid();
        }
        public GuidUser(string name) : this() { UserName = name; }
    }

    private class GuidUserContext : IdentityDbContext<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> { }
    private class GuidUserStore : UserStore<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
        public GuidUserStore(DbContext context)
            : base(context) {
        }
    }
    private class GuidRoleStore : RoleStore<GuidRole, Guid, GuidUserRole> {
        public GuidRoleStore(DbContext context)
            : base(context) {
        }
    }

    [TestMethod]
    public async Task CustomUserGuidKeyTest() {
        var manager = new UserManager<GuidUser, Guid>(new GuidUserStore(new GuidUserContext()));
        GuidUser[] users = {
            new GuidUser() { UserName = "test" },
            new GuidUser() { UserName = "test1" }, 
            new GuidUser() { UserName = "test2" },
            new GuidUser() { UserName = "test3" }
            };
        foreach (var user in users) {
            UnitTestHelper.IsSuccess(await manager.CreateAsync(user));
        }
        foreach (var user in users) {
            var u = await manager.FindByIdAsync(user.Id);
            Assert.IsNotNull(u);
            Assert.AreEqual(u.UserName, user.UserName);
        }
    }
臧令
2023-03-14

使用斯特凡·塞布拉克的答案和本·福斯特的博客文章ASP。NET,我提出了以下解决方案,我已将其应用于ASP。NET Identity 2.0,由Visual Studio 2013生成。

该解决方案使用整数作为用户的主键,还允许在不访问数据库的情况下获取当前登录用户的ID。

以下是步骤,您需要遵循:

默认情况下,AccountController使用类作为主键类型,这些类使用字符串。我们需要创建以下类,这些类将使用int。我在一个文件中定义了以下所有类:AppUser。cs

public class AppUser :
    IdentityUser<int, AppUserLogin, AppUserRole, AppUserClaim>,
    IUser<int>
{

}

public class AppUserLogin : IdentityUserLogin<int> { }

public class AppUserRole : IdentityUserRole<int> { }

public class AppUserClaim : IdentityUserClaim<int> { }

public class AppRole : IdentityRole<int, AppUserRole> { }

它也将是有用的,有一个自定义Claims主体,这将很容易地暴露用户的ID

public class AppClaimsPrincipal : ClaimsPrincipal
{
    public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
    { }

    public int UserId
    {
        get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); }
    }
}

我们的应用程序的数据库上下文将扩展IdtyDbContext,它默认实现所有与身份验证相关的DbSets。即使DbContext。OnModelCreating是一个空方法,我也不确定IdtyDbContext。OnModelCreating,所以覆盖时,记得调用base。OnModelCreating(ModelBuilder)AppDbContext.cs

public class AppDbContext :
    IdentityDbContext<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>
{
    public AppDbContext() : base("DefaultConnection")
    {
        // Here use initializer of your choice
        Database.SetInitializer( new CreateDatabaseIfNotExists<AppDbContext>() );
    }


    // Here you define your own DbSet's



    protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
        base.OnModelCreating( modelBuilder );

        // Here you can put FluentAPI code or add configuration map's
    }
}

AppUserStore。cs

public interface IAppUserStore : IUserStore<AppUser, int>
{

}

public class AppUserStore :
    UserStore<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>,
    IAppUserStore
{
    public AppUserStore() : base( new AppDbContext() )
    {

    }

    public AppUserStore(AppDbContext context) : base(context)
    {

    }
}

AppUserManager。cs

public class AppUserManager : UserManager<AppUser, int>
{
    public AppUserManager( IAppUserStore store ) : base( store )
    {

    }
}

将所有UserManager更改为AppUserManagerUserStore更改为AppUserStore等。举一个这个构造函数的例子:

public AccountController()
    : this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) )
{
}

public AccountController(AppUserManager userManager)
{
    UserManager = userManager;
}

在步骤1中,我们创建了AppClaimsPrincipal,它公开了从ClaimType中提取的用户ID。Sid。然而,为了使这个声明可用,我们需要在登录用户时添加它。在AccountController中,一个SingInAsync方法负责登录。我们需要在这个方法中添加一行,以添加索赔。

private async Task SignInAsync(AppUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    // Extend identity claims
    identity.AddClaim( new Claim( ClaimTypes.Sid, user.Id.ToString() ) );

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

要轻松访问控制器中当前登录的用户ID,请创建抽象的BaseController,控制器将从中派生。在基本控制器中,创建一个当前用户,如下所示:

public abstract class BaseController : Controller
{
    public AppClaimsPrincipal CurrentUser
    {
        get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); }
    }


    public BaseController()
    {

    }
}

从现在开始,您可以使用货币用户。控制器中的UserId访问当前登录用户的ID,而无需访问数据库。您可以使用它仅查询属于用户的对象。

您不必关心用户主键的自动生成——毫不奇怪,实体框架在创建表时默认使用整数主键的标识。

警告请记住,如果您在已经发布的项目中实现它,对于已经登录的用户,请参见ClaimsType。Sid将不存在,并且在AppClaimsPrincipal中,FindFirst将返回null。您需要强制注销所有用户或在AppClaimsPrincipal中处理此情况

 类似资料:
  • 问题内容: 在我的特定情况下,我正在使用区分列策略。这意味着我的JPA实现(hibernate)创建带有特殊 DTYPE 列的 users 表。此列包含实体的类名称。例如,我的 用户 表可以具有 TrialUser* 和 PayingUser的 子类。这些类名称将在 DTYPE 列中,以便EntityManager从数据库加载实体时,它知道要实例化的类的类型。 *** __ 我尝试了两种转换实体类

  • 问题内容: 我正在使用hibernate作为持久层。存在于同一表中的2个实体通过单表继承策略扩展了一个超类。 我有一个ID为4的B实例。如何将此实例的类型更改为C并保留其ID(4)? 上面的代码因 有可能吗? 问题答案: Hibernate尝试使持久性尽可能地透明-这意味着它尝试遵循与普通Java对象相同的原则。现在,用Java改写您的问题,您将获得: 如何将B类的实例转换为(不兼容的)C类的实例

  • 问题内容: 我有以下脚本: 使用tor和SocksiPy 现在,我想更改每个请求的tor身份,例如: 我怎样才能做到这一点? 问题答案: 今天,我对这个问题进行了很多搜索,最后设法回答了自己。但是在我不得不说pirvoxy和tor应该正确配置之前。第一个脚本,然后是一些配置: 上面的脚本获取了新的IP并从ifconfig.me网站进行了检查。关于配置:我们需要Privoxy。要将TOR与HTTP连

  • 问题内容: 我已经在计算机上设置了一个新的MySQL实例,每次添加用户时,它将Authentication Type设置为。 即使将身份验证类型设置为“ ”,也会发生这种情况,然后在保存用户时将其更改。我也将默认身份验证插件更改为“ ”,但仍会继续这样做。 有了它,我无法从.net核心连接到数据库,因为出现错误说明: MySqlException:任何可用插件均不支持身份验证方法“ caching

  • 问题内容: 我想在Chart.JS水平条形图中将字体更改为更时髦的字体。我已经尝试了以下方法,但是都没有用: 我还读到这会起作用: …但是这段代码会去哪里,以及它应该看起来如何?我尝试了这个: …但也没有效果 对于完整图片/上下文,这是组成此图表的所有代码: 的HTML JQUERY 我什至尝试了这个: 的CSS 的HTML …但是我认为画布绘制会照顾字体的外观,因为添加字体没有区别。 更新 我试

  • 问题内容: 谁能告诉我如何识别并切换到只有标题的iframe? 我已经尝试通过下面的代码,但不能正常工作 问题答案: 您可以使用cssSelector