2015-04-03 2 views
2

Я создал пользовательский класс под названием Person хранить имя, адрес и т.д. Этот класс/модель перекрестных ссылок от других моделей, в том числе ApplicationUser:Почему мое пользовательское свойство объекта в ApplicationUser null?

public class ApplicationUser : IdentityUser 
{ 
    public Person Person { get; set; } 

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) 
    { 
     // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 
     var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 
     // Add custom user claims here 
     return userIdentity; 
    } 
} 

В одном из моих контроллеров, я использую следующие код, чтобы получить текущий пользователь вошел в систему и получить его Person объект, например, так:

 var user = UserManager.FindById(User.Identity.GetUserId()); 
     var person = user.Person; 

Мой Person класс также определяется в ApplicationDbContext:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public ApplicationDbContext() 
     : base("MyContext", throwIfV1Schema: false) 
    { 
    } 

    public DbSet<Person> People { get; set; } 
} 

Когда я проверяю user, я вижу, что Entity Framework заполнил объект, потому что я вижу идентификатор пользователя, адрес электронной почты, пароль хэша, все! Все исключаяPerson property! Тем не менее, я вижу в базе данных, что соответствующая строка не null, но имеет правильный идентификатор для Person.

Я новичок в структуре ASP.NET/MVC/Entity, и я прочитал, что по умолчанию использует ленивую загрузку. Это то, что я испытываю? Если да, как я могу сказать, что Entity использует активную загрузку в свойстве Person? Если нет, что я делаю неправильно?

+0

Убедитесь, что вы присвоили свойство 'Person' в методе' UserManager.FindById' ... –

+0

1) Вы добавили 'IDbSet ' в 'ApplicationDbContext'? & 2) Попытайтесь пометить свойство ApplicationUser.Person как виртуальное (так что класс прокси-сервера может лениво загрузить его). - Мне кажется, что БД не знает, что она существует как отношения и может потребоваться использовать неявные соглашения/атрибуты/текущую привязку к модели, чтобы рассказать об этом EF. –

+0

@BradChristie 1) Да, это я определил в своем «ApplicationDbContext». 2) Я попробую отметить его как виртуальный. –

ответ

5

Это, вероятно, проблема отображения. Сочетания структур Entity Framework слишком сложны для объяснения здесь, но я укажу, где может быть проблема.

Удостоверьтесь, что ApplicationUser имеет свойство внешнего ключа Person таким образом, чтобы Entity Framework мог его понять. Entity Framework основана на соглашениях, поэтому она будет искать свойство PersonId в вашем классе ApplicationUser. Если вы не хотите использовать имя по умолчанию, вы можете использовать свободную конфигурацию в своем Контексте OnModelCreating, чтобы присвоить ему свое имя.

Я лично считаю, что всегда полезно вручную сопоставить все ваши отношения. Вот пример:

public void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    builder.Entity<ApplicationUser>().HasRequired(m => m.Person).HasForeignKey(d => d.Person) 
} 

Пожалуйста, обратитесь к этой ссылке для получения дополнительной информации: https://msdn.microsoft.com/en-us/data/jj591620.aspx

+0

Ну, это сработало! Я добавил 'modelBuilder.Entity (). HasOptional (m => m.Person);' моему методу OnModelCreating' и теперь он работает. Спасибо за помощь, @andrerpena! Тем не менее, я до сих пор не понимаю, почему Entity Framework успешно вставляла данные в базу данных правильно, но не читала ее. Я бы подумал, что вставка тоже потерпит неудачу. –

+0

Я рад, что все получилось отлично. Entity Framework правильно вставляла данные, потому что она признавала существование Person, но не так, как это связано с ApplicationUser. –

1

Я бы сделал Person class inherit от IdentityUser или ApplicationUser. Тогда, я бы следующие в классе DbContext:

DbSet<Person> People {get;set;} 

Затем вы можете использовать это:

MyDbContext db = new MyDbContext();  
string userid = User.Identity.GetUserId(); 
var user = db.People.Single(p=>p.Id == userid); 
+1

, или он мог бы просто добавить все свойства Person в класс «ApplicationUser». –

+0

Мой класс «Личность» также используется другими классами в моем проекте, которые не обязательно «ApplicationUser's», поэтому я не смогу унаследовать его. –

0

В рамочной сущности коды первого приближения рамка субъекта делает первое целочисленное свойство в качестве первичного ключа. Таким образом, здесь вы добавляете ссылку класса Person в класс приложения User.Вы можете попробовать это, как:

[ForeignKey ("PersonId")]

общественного виртуального Person Person {получить; набор;}

общественности Int PersonId {получить; набор;}

Этот сделает PersonId в качестве внешнего ключа в приложении Таблица пользователей. Вы также можете сделать его нулевым.

public int? PersonId {get; set;}

Оттуда вы можете получить объект Id объекта Person, вставленный в таблицу пользователя приложения, а затем вы можете получить свойства объекта person.

Надеюсь, это поможет вам, поскольку это отображает связь между двумя таблицами.

Смежные вопросы