Игнорируется связь One-to-Many в IdentityDbContext

156
10 ноября 2018, 14:50

Есть следующий контекст БД:

public class AppIdentityContext : IdentityDbContext<UserAccount, UserRole, int>
{
    public AppIdentityContext(DbContextOptions<AppIdentityContext> options) : base(options) { }
    public DbSet<RefreshToken> RefreshTokens { get; set; } 
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<RefreshToken>()
            .HasKey(rt => rt.Refresh);
        builder.Entity<RefreshToken>()
            .HasOne(rt => rt.UserAccount)
            .WithMany(ua => ua.RefreshTokens)
            .HasForeignKey(rt => rt.UserId);
    }
}

Сами классы сущностей:

public class UserAccount : IdentityUser<int>
{
    // other properties
    public virtual ICollection<RefreshToken> RefreshTokens { get; set; }
}
public class RefreshToken
{
    public string Refresh { get; set; }
    // other properties
    public int UserId { get; set; }
    public virtual UserAccount UserAccount { get; set; }
}

Далее я получаю RefreshToken в методе:

public async Task<RefreshToken> GetByRefreshAsync(string token)
{
    return await _context.RefreshTokens.FirstOrDefaultAsync(t => t.Refresh == token);
}
//...
var currentToken = await _tokenRep.GetByRefreshAsync(refreshToken);
if (currentToken.UserAccount == null)
{
    //...
}
//...

Так вот, похоже, что он игнорирует связь, установленную ранее в DbContext, потому что UserAccount всегда null.

Судя по логам, он не запрашивает UserAccount ни в момент получения RefreshToken, ни в момент обращения к полю UserAccount.

Если же явно запросить пользователя, то всё отрабатывает отлично.

var userAccount = await _userManager.FindByIdAsync(currentToken.UserId.ToString());
if (userAccount == null)
{
    //...
}
//...
Answer 1

EF до 2.1 не поддерживает ленивую загрузку, даже если у вас именно 2.1 её нужно отдельно включать.

Включив нужно проверить, что выполнены условия для ленивой загрузки (классы публичные, свойства виртуальные).

Ну и традиционно рекомендую не включать ленивую загрузку, указывать явно в каждом случае, что вам нужны за поля. Подгрузите их явно:

await _context.RefreshTokens.Include(x => x.UserAccount )
                            .FirstOrDefaultAsync(t => t.Refresh == token);

См. также:

  • Entity Framework Core и Lazy Load
READ ALSO
Не понятная ошибка TorSharp

Не понятная ошибка TorSharp

Есть два метода которые я использую, и если я вызываю второй раз его прегрузку то выдает ошибку, ошибку напишу ниже Вот код методов

176
C# наполнение массива textBox&#39;ами [дубликат]

C# наполнение массива textBox'ами [дубликат]

На данный вопрос уже ответили:

174
C# UDP Отправка сервера к клиенту байт выдает ошибку

C# UDP Отправка сервера к клиенту байт выдает ошибку

Всем привет! Когда сервер отправляет байт данных на уже отключенный клиент то я получаю вот такое исключение:

196
Удаление объекта из БД и combobox WPF

Удаление объекта из БД и combobox WPF

Ситуация следующая: у меня есть База данных(БД) Department у этой БД два поля id и DepNameЗадача: по нажатию кнопки "Удалить" - удалить объект из БД Department...

154