У меня есть старый проект ASP.NET MVC, использующий Identity/SQL Server, который отлично работает уже более десяти лет, и сейчас я пытаюсь запустить новую версию, использующую ASP.NET Core.
Я расширил IdentityUser
до ApplicationUser
с помощью некоторых настраиваемых полей, которые нормально поступают из базы данных. Но у меня также есть внешний ключ к отдельной сущности, которая возвращает NULL, что бы я ни пытался. В старом проекте все это работало нормально.
ApplicationUser
класс:
public partial class ApplicationUser : IdentityUser
{
public string CustomField { get; set; }
public Guid? EntityId { get; set; }
[ForeignKey("EntityId")]
public virtual EntityObject? Entity { get; set; }
}
Класс внешнего ключа EntityObject
:
[PrimaryKey("EntityId")]
public class EntityObject
{
[Key]
public System.Guid EntityId { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
}
DbContext
класс:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
CustomField
заполняется, но EntityObject
всегда имеет значение NULL там, где его не было в старом проекте.
Я просмотрел здесь разные темы, пробуя разные комбинации (например, реализовав OnModelCreating()
), но безрезультатно. У меня очень большой опыт работы с базами данных, и, поскольку это устаревшая база данных, миграция баз данных затруднена, поэтому я стараюсь избегать использования как можно большего количества.
Обновлять Это код, который я использую для получения информации о пользователе, и именно здесь я вижу, что объект Entity внешнего ключа имеет значение null:
ApplicationUser user = userManager.GetUserAsync(User).Result;
В сгенерированном SQL-коде в консоли я заметил, что он запрашивает только таблицу AspNetUsers и не пытается выполнить соединение.
Я обновил код, чтобы найти данные. Да, внешний ключ на месте и все данные есть. Мой старый проект (также использующий Identity) возвращает данные. В сгенерированном SQL-коде в консоли я заметил, что он запрашивает только таблицу AspNetUsers и не пытается выполнить соединение.
Entity Framework Core не выполняет отложенную загрузку «из коробки» — это все равно можно сделать, но помните о предупреждении на приведенной выше странице — вместо этого вам нужно указать, какие свойства навигации включать/загружать. -- вот свойство Entity
.
Когда вы будете работать напрямую с ApplicationDbContext
, это будет выглядеть, как показано ниже; обратите внимание на утверждение Include
.
var user = await dbc.Users
.Include(o => o.Entity)
.FirstOrDefaultAsync();
Поскольку вы имеете дело с ASP.NET Identity UserManager, а не напрямую с ApplicationDbContext
, вы можете настроить его так, чтобы он всегда загружал это Entity
свойство навигации, настроив AutoInclude
для данного свойства в переопределении OnModelCreating
вашего ApplicationDbContext
.
Ссылка на документацию.
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<ApplicationUser>().Navigation(e => e.Entity).AutoInclude();
}
Из документации AutoInclude:
Определяет, должна ли эта навигация автоматически включаться в запрос.
Примечание; не используйте .Result
; вместо этого await
позвонили.
var user = await userManager.GetUserAsync(User);
На StackOverflow много информации об этом.
Это здорово, спасибо. Он получил загрузку данных моего внешнего ключа. И еще кое-что. У меня есть еще один внешний ключ в таблице User, которая представляет собой таблицу ссылок один-ко-многим. Теперь это работает с AutoInclude, но возможно ли автовключение «дочернего элемента». Я знаю, что вы можете вложить .Include().ThenInclude(), но не вижу, как это сделать в OnModelCreating?
Аналогичным образом вам придется применить AutoInclude
для свойств навигации к этим дочерним объектам; например builder.Entity<EntityObject>().Navigation(e => e.ChildEntity).AutoInclude();
.
Ах да, конечно. Спасибо большое все решено
Вы можете проверить, существует ли в вашей базе данных связанный внешний ключ, например
FK_AspNetUsers_EntityObjects_EntityId
, и заполнены ли соответствующие данные в таблицахEntityObject
иaspnetUsers
. Если связь внешнего ключа и данные заполнены, как вы запрашиваете данные? Можете ли вы поделиться соответствующим кодом запроса?