Пользовательский идентификатор пользователя и расширяющий профиль MVC

Я пытаюсь расширить идентификационные данные пользователя в отдельной таблице, но не заселяю.

  public class MyUserInfo
  {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

  }

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

    public MyUserInfo MyUserInfo { get; set; }
 }

//Fetching the user data

var userStore = new UserStore<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>(db);
var userManager = new UserManager<AppUser, int>(userStore);

var user = userManager.FindById(1);

user.MyUserInfo, показывающий null. Но в db у нас есть соответствующие пользовательские данные.

Я видел много сообщений, где без настройки кажется работающим, но для меня я модифицировал id, сохраненный как целое, и изменил имя таблицы.

Ответы

Ответ 1

Идентификатор пользователя UserManager автоматически не вытягивает UserInfo (или любую другую таблицу Entity с внешней навигацией)

Вы расширили схему идентификации, но вы не расширили UserManager.

Ни один из методов UserManager для получения пользователя (например, findbyid(), FindByIdAsync()) не извлекает дочерние объекты с помощью Entity Framework Navigation.

Взгляните на GitHub FindByIdAsync

    public virtual Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
    {
        cancellationToken.ThrowIfCancellationRequested();
        ThrowIfDisposed();
        var id = ConvertIdFromString(userId);
        return Users.FirstOrDefaultAsync(u => u.Id.Equals(id), cancellationToken);
    }

Метод возвращает только User Entity. Нет никакой функции для проверки "дочерних" таблиц навигации, не говоря уже о том, чтобы вытащить их.


Вы можете расширить UserManager, реализовав такой метод.

В противном случае вам придется вручную вытащить дочерний объект Entity после извлечения UserId. Вот как я это сделал:

            var UserId = User.Identity.GetUserId<int>();

            try
            {
                user = await UserManager.FindByIdAsync(UserId );
            }
            catch (Exception e)
            {
                return BadRequest(e.Message);
            }

            var userInfo = AuthContext.UserInfo.
                   FirstOrDefault(u => u.Id == user.UserInfo_Id);

Примечание. Я также должен был убедиться, что у моего ApplicationUser был внешний ключ для моего UserInfo Entity:

public class ApplicationUser : IdentityUser
{
    [ForeignKey("UserInfo")]
    public int UserInfo_Id { get; set; }

    public virtual UserInfo UserInfo { get; set; }

и в моем построителе моделей

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
          .HasRequired<UserInfo>(profile => profile.UserInfo);


        base.OnModelCreating(modelBuilder);
    }

Ответ 2

Я думаю, что проблема здесь не связана с идентификацией asp.net, а с инфраструктурой сущности. Поскольку вы получаете данные из userManager.FindById(1), но вы не получаете относительные данные из таблицы MyUserInfo, потому что отношения не существуют.

Измените объект MyUserInfo на

public class MyUserInfo
{
    //change it from Id to AppUserId
    public int AppUserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }   
    //add this virtual property
    public virtual AppUser User { get; set; }
}

Затем добавьте миграцию и обновите базу данных. Структура Entity сделает отношение между таблицами и AppUserId будет внешним ключом (соглашение о первом соглашении с кодом).