Как изменить тип идентификатора в 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? (Возможно, есть преимущества, которые я упускаю.)



спасибо...



-Бен

786   5  

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.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> { }

также будет полезно иметь пользовательский 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.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
    }
}

3. Создать пользовательский UserStore и UserManager, который будет использовать выше

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 )
    {

    }
}

4. Изменить AccountController использовать ваши пользовательские классы

изменить все UserManager до AppUserManager,UserStore до AppUserStore etc. Возьмем пример этого конструктора:

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

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

5. Добавьте идентификатор пользователя в качестве требования к ClaimIdentity хранится в файле cookie

в шаге 1, мы создали AppClaimsPrincipal, который выставляет UserId, взятый из ClaimType.Sid. Однако, чтобы это утверждение было доступно, нам нужно добавить его при входе в систему пользователя. В AccountController a 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);
}

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

    Ничего не найдено.