Как изменить тип идентификатора в Microsoft.сеть САШ.Тождественность.EntityFramework.IdentityUser
(ASP.NET MVC 5, EF6, VS2013)
Я пытаюсь выяснить, как измените тип поля " Id " со string на int тип:
Microsoft.AspNet.Identity.EntityFramework.IdentityUser
чтобы новые учетные записи пользователей были связаны с целочисленным идентификатором, а не с идентификатором GUID. Но похоже, что это будет сложнее, чем просто добавить новое свойство Id с типом int в мой производный пользовательский класс. Взгляните на эту сигнатуру метода:
(из сборки Microsoft.сеть САШ.Тождественность.Ядро.dll)
public class UserManager<TUser> : IDisposable where TUser : global::Microsoft.AspNet.Identity.IUser
{
...
public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
...
}
так что кажется, что есть и другие методы запеченные в ASP.NET структура идентификации, которая требует, чтобы идентификатор пользователя был строкой. Нужно ли мне также переопределять эти классы?
объяснение того, почему я не хочу хранить GUID для идентификаторов в пользовательской таблице:
- там будут другие таблицы, которые связывают данные с таблицей пользователей через внешний ключ. (Когда пользователи сохраняют контент на сайте.) Я вижу нет причина использовать больший тип поля и тратить дополнительное пространство базы данных без явных преимуществ. (Я знаю, что есть и другие сообщения об использовании GUIDs vs int ids, но, похоже, многие предполагают, что int ids быстрее и используют меньше места, что все еще оставляет меня в недоумении.)
- Я планирую предоставить конечную точку restful, чтобы пользователи могли получать данные о конкретном пользователе. Я думаю:
/users/123/name
чище, чем
/users/{af54c891-69ba-4ddf-8cb6-00d368e58d77}/name
кто-нибудь знает, почему ASP.NET команда решили реализовать идентификаторы таким образом? Я близорук в попытке изменить это на тип int? (Возможно, есть преимущества, которые я упускаю.)
спасибо...
-Бен
5 ответов:
поэтому, если вы хотите int ids, вам нужно создать свой собственный класс POCO IUser и реализовать свой IUserStore для вашего пользовательского класса IUser в версии 1.0 RTM.
Это то, что у нас не было времени, чтобы поддержать, но я смотрю на то, чтобы сделать это легко(ier) в 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); } }
с помощью Стефан Чебулакответ и отличная статья в блоге Бена Фостера ASP.NET личность раздели догола я придумал ниже решение, которое я применил к ASP.NET идентичность 2.0 С помощью сгенерированной Visual Studio 2013
AccountController.решение использует целое число в качестве первичного ключа для пользователей, а также позволяет получить идентификатор пользователя, вошедшего в систему в базе данных.
здесь шаги, вы должны следовать:
1. Создание пользовательских классов, связанных с пользователем
по умолчанию
AccountControllerиспользует классы, которые используютstring, как тип первичного ключа. Нам нужно создать ниже классы, которые будут использовать . Я определил все ниже классы в одном файле:AppUser.cspublic 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> { }также будет полезно иметь пользовательский ClaimsPrincipal, который будет легко выставлять идентификатор пользователя
public class AppClaimsPrincipal : ClaimsPrincipal { public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal ) { } public int UserId { get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); } } }2. Создание пользовательского
IdentityDbContextконтекст базы данных нашего приложения будет расширяться
IdentityDbContext, который реализует по умолчанию все наборы данных, связанные с проверкой подлинности. Даже еслиDbContext.OnModelCreating- это пустой метод, я не уверен, оIdentityDbContext.OnModelCreating, поэтому при переопределении, не забудьте позвонитьbase.OnModelCreating( modelBuilder )AppDbContext.cspublic 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 } }3. Создать пользовательский
UserStoreиUserManager, который будет использовать выше
AppUserStore.cspublic 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.cspublic class AppUserManager : UserManager<AppUser, int> { public AppUserManager( IAppUserStore store ) : base( store ) { } }4. Изменить
AccountControllerиспользовать ваши пользовательские классыизменить все
UserManagerдоAppUserManager,UserStoreдоAppUserStoreetc. Возьмем пример этого конструктора:public AccountController() : this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) ) { } public AccountController(AppUserManager userManager) { UserManager = userManager; }5. Добавьте идентификатор пользователя в качестве требования к
ClaimIdentityхранится в файле cookieв шаге 1, мы создали
AppClaimsPrincipal, который выставляет UserId, взятый изClaimType.Sid. Однако, чтобы это утверждение было доступно, нам нужно добавить его при входе в систему пользователя. ВAccountControlleraSingInAsyncметод отвечает за вход. Нам нужно добавить строку к этому методу нужно добавить утверждение.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); }6. Создайте
BaseControllerСCurrentUserсвойствачтобы иметь легкий доступ к текущему идентификатору пользователя в контроллерах, создайте абстрактный
BaseController, из которого будут выводиться ваши контроллеры. ВBaseControllerсоздатьCurrentUserследующим образом:public abstract class BaseController : Controller { public AppClaimsPrincipal CurrentUser { get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); } } public BaseController() { } }7. Наследовать контроллеры от
BaseControllerи наслаждатьсяотныне, вы можете использовать
CurrentUser.UserIdв контроллерах для доступа к Идентификатор текущего пользователя, вошедшего в систему без доступа к базе данных. Вы можете использовать его, чтобы запросить только те объекты, которые принадлежат Пользователю.вам не нужно заботиться о автоматической генерации первичных ключей пользователя - неудивительно, что Entity Framework по умолчанию использует Identity для целых первичных ключей при создании таблиц.
предупреждение! имейте в виду, что если вы реализуете его в уже выпущенном проекте, для уже зарегистрированных пользователей
ClaimsType.Sidне будет существовать иFindFirstвернет null вAppClaimsPrincipal. Вам нужно либо принудительно выйти из системы всех пользователей, либо обработать этот сценарий вAppClaimsPrincipal
@HaoKung
мне удалось сделать int id с вашими ночными сборками. Пользователь.Тождественность.Проблема GetUserId () все еще существует, но я только что сделал int.parse () на данный момент.
самым большим сюрпризом было то, что мне не нужно было создавать ID самостоятельно, db был сделан с Identity id, и он каким-то образом автоматически устанавливался для новых пользователей Oo...
модель:
: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...
П. С. Не могу писать комментарии, поэтому я сделал ответ, К сожалению.
в Visual Studio 2013 веб-приложение по умолчанию использует строковое значение для ключа для учетных записей пользователей. ASP.NET удостоверение позволяет изменить тип ключа в соответствии с требованиями к данным. Например, можно изменить тип ключа из строки в целое число.
http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity
в этом разделе по ссылке выше показано, как начать с веб-сайта по умолчанию применение и изменение ключа учетной записи Пользователя на целое число. Вы можете использовать те же изменения для реализации любого типа ключа в вашем проекте. В нем показано, как внести эти изменения в веб-приложение по умолчанию, но вы можете применить аналогичные изменения к настраиваемому приложению. Он показывает изменения, необходимые при работе с MVC или веб-формами.
в основном вы должны :
- измените тип ключа на int в классе Identity user
- Добавить индивидуальные классы идентичности, которые используют int в качестве ключа
- Измените класс контекста и диспетчер пользователей, чтобы использовать int в качестве ключа
- Измените конфигурацию запуска, чтобы использовать int в качестве ключа
- Измените AccountController, чтобы передать int как ключздесь это ссылка, где все шаги объясняются для достижения этой цели.
Comments