Внешний ключ обновления ядра EF не обновляет свойство навигации

#c# #linq #asp.net-core #entity-framework-core

Вопрос:

У меня есть таблица под названием User , содержащая 3 внешних ключа CountryID , NationalityID и EducationID

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

Поэтому, чтобы добиться этого, я сделал это, как показано ниже

 var user= await _dbContext.Users
.Include(x => x.Country)
.Include(x => x.Nationality)
.Include(x => x.Education)
.Where(P => P.userID == request.userId)
.AsTracking()
.FirstOrDefaultAsync();
 

Затем, если пользователь хочет обновить, я это сделаю

 user.CountryID= request.CountryID;

user.NationalityID= request.NationalityID;

await _dbContext.SaveChangesAsync();

var userDTO = _mapper.Map<UpdateUserResponseDTO>(user);
 

Проблема в том, что в ответе JSON данные о стране и национальности, такие как их имена и другие данные, возвращаются в виде null

Что я сделал, чтобы исправить это, так это добавил

 _dbContext.Entry(user).Reference(x => x.Country).Load();

_dbContext.Entry(user).Reference(x => x.Nationality).Load();

_dbContext.Entry(user).Reference(x => x.Education).Load();

await _dbContext.SaveChangesAsync();
 

Но не уверен, каково влияние использования load или как efficient это происходит?
и почему asTracking не отслеживаются изменения, внесенные в правила навигации?
И является ли использование Load() более эффективным, чем повторная загрузка сущности пользователя после ее обновления? нравится делать

  var user= await _dbContext.Users
    .Include(x => x.Country)
    .Include(x => x.Nationality)
    .Include(x => x.Education)
    .Where(P => P.userID == request.userId)
    .FirstOrDefaultAsync();
 

Комментарии:

1. Конечно, последний будет быстрее, так как для него требуется всего одна поездка на север. Для каждого груза вам нужна специальная поездка.

2. нет ли решения этой проблемы с использованием теста?

3. Лучшее — это враг хорошего. Вы должны быть счастливы, если все работает должным образом, и не пытаться все испортить.

4. Этого недостаточно, если все работает только из-за качества и эффективности кода.

5. Когда вы выполняете сопоставление, вы можете обновить навигационное свойство с фактическими значениями новой связи. Поэтому сопоставьте User.Nationality с новым экземпляром Nationality, который вы устанавливаете. Проблема в том, что, как только вы обновите этот идентификатор, ему потребуется загрузить его запись в память, для чего в какой-то момент потребуется еще один вызов бд, если это навигационное свойство важно.

Ответ №1:

Обязательно добавьте виртуальное ключевое слово в свой контекстный класс перед любым свойством набора данных, чтобы оно было таким

 public virtual DbSet<type> propname {get;set;}
 

А также добавьте виртуальное ключевое слово перед свойствами навигации в классах вашего домена, чтобы это было так

 public class User
{
public virtual Country Country {get;set;} 
}
public class Country 
{
public virtual ICollection<User> Users {get;set;} 
} 
 

Эти конфигурации помогут entity framework унаследовать ваши свойства навигации и применить к ним отложенную загрузку

Комментарии:

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

2. Например, dbcontext. Запись(объект пользователя ). Государство=государство-субъект. Модифицированный