我在 ASP.NET 6 中有一个应用程序,它使用 Entity Framework 核心作为 ORM。作为旁注,我对 ORM 没有太多经验。
我有以下实体:
应用程序用户:
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; } = string.Empty;
public bool IsProfessional { get; set; } = false;
public ICollection<Address>? Addresses { get; set; } = default;
}
一个用户可以有多个地址,因此有 ICollection 属性。
地址:
public class Address
{
public string Id { get; set; } = string.Empty;
public string UserId { get; set; } = string.Empty;
public ApplicationUser User { get; set; } = default;
public string Street { get; set; } = string.Empty;
public string Number { get; set; } = string.Empty;
public string Neighborhood { get; set; } = string.Empty;
public string ZipCode { get; set; } = string.Empty;
public string CityId { get; set; } = string.Empty;
public City City { get; set; } = default;
}
Address 用户包含用户的 UserId 和用于导航目的的 User 属性。它还包含一个 CityId 和一个 City 属性,也用于导航目的。
城市:
public class City
{
public string Id { get; set; }
public string Name { get; set; } = string.Empty;
public State State { get; set; } = default;
public ICollection<Address>? Addresses { get; set; } = default;
}
一个城市属于多个地址,所以这里我有集合地址用于导航目的。
我正在使用身份框架来管理我的用户。在我的代码中的某个时刻,我需要加载用户(使用 UserManager)和用户相关的属性,例如地址,以及与地址相关的城市。
这是我遇到问题的片段:
public async Task<GetUserQueryResponse> Handle(GetUserQuery request, CancellationToken cancellationToken)
{
var user = await _userManager.Users
// Here I include the Addresss and hope that the City property is loaded
// for each address
.Include(u => u.Addresses)
.Where(u => u.Id == request.UserId).FirstOrDefaultAsync();
var userAddresses = new List<GetAddressForUserDTO>();
foreach (var address in user.Addresses)
{
userAddresses.Add(new GetAddressForUserDTO()
{
Id = address.Id,
UserId = address.Id,
Street = address.Street,
Number = address.Number,
Neighborhood = address.Neighborhood,
ZipCode = address.ZipCode,
City = address.City.Name, // PROBLEM: The city is null, was not loaded.
State = address.City.State.Abbreviation // PROBLEM: The city is null.
});
}
// rest of the code
}
这里是调试时的输出:
有没有一种方法可以编写此查询或更改实体以允许框架在编写此类查询时加载相关属性?我做错了什么?
您需要also包括
City
导航属性:
var user = await _userManager.Users
.Include(u => u.Addresses)
// loading the address, also get the City
.ThenInclude(a => a.City)
.Where(u => u.Id == request.UserId)
.FirstOrDefaultAsync();