EntityFramework 核心延迟加载 returns 所有相关表
EntityFramework Core Lazy Loading returns all related tables
我的数据库中有 3 个表:
国家
状态
城市
我有一个 API 应该 return 一个国家及其州。
但是,当我尝试这样做时,我最终得到一个 JSON 对象,其中包含国家、统计数据以及每个州下的所有城市
我的代码是这样的(Eager 和 Lazy return 相同):
//Eager Loading
var countries = await _context.Countries.Include(s=>s.States).ToListAsync(cancellationToken);
//Lazy Loading
var countries = await _context.Countries.ToListAsync(cancellationToken);
如何只加载州而离开城市?
我的建议是永远不要 return 个实体。只要实体的 DbContext 作为数据模型的表示,实体就应该存在。视图或 API 使用的模型有不同的用途,应该是 EF 可以填充的简单、可序列化的 POCO。这让它们只适合您 view/consumer 关注的数据。在您的情况下,您只关心国家和州,而不关心城市或其他相关位。您甚至可能不需要关于一个国家或州的所有数据。让 EF 仅针对所需数据构建查询。这提高了查询的性能,减少了服务器和客户端的内存使用,并避免了序列化的陷阱。 (即循环引用)实体应始终代表实体的完整状态。关闭延迟加载和传递不完整的实体图很容易导致错误,因为接受实体引用并面对 null/empty 引用的方法将不知道该引用是未加载还是不存在的区别.
[Serializable]
public class CountryViewModel
{
public int CountryID { get; set; }
public string CountryName { get; set; }
public IEnumerable<StateViewModel> States { get; set; } = new List<StateViewModel>();
}
[Serializable]
public class StateViewModel
{
public int StateID { get; set; }
public string StateName { get; set; }
}
然后在获取国家和州时:
var countries = await _context.Countries
.Select(x => new CountryViewModel
{
CountryId = x.CountryId,
CountryName = x.Name,
States = x.States.Select(s => new StateViewModel
{
StateId = s.StateId,
StateName = s.Name
}).ToList()
}).ToListAsync(cancellationToken);
利用 Automapper,这可以很容易地简化为:
var countries = await _context.Countries
.ProjectTo<CountryViewModel>()
.ToListAsync(cancellationToken);
我的数据库中有 3 个表: 国家 状态 城市
我有一个 API 应该 return 一个国家及其州。
但是,当我尝试这样做时,我最终得到一个 JSON 对象,其中包含国家、统计数据以及每个州下的所有城市
我的代码是这样的(Eager 和 Lazy return 相同):
//Eager Loading
var countries = await _context.Countries.Include(s=>s.States).ToListAsync(cancellationToken);
//Lazy Loading
var countries = await _context.Countries.ToListAsync(cancellationToken);
如何只加载州而离开城市?
我的建议是永远不要 return 个实体。只要实体的 DbContext 作为数据模型的表示,实体就应该存在。视图或 API 使用的模型有不同的用途,应该是 EF 可以填充的简单、可序列化的 POCO。这让它们只适合您 view/consumer 关注的数据。在您的情况下,您只关心国家和州,而不关心城市或其他相关位。您甚至可能不需要关于一个国家或州的所有数据。让 EF 仅针对所需数据构建查询。这提高了查询的性能,减少了服务器和客户端的内存使用,并避免了序列化的陷阱。 (即循环引用)实体应始终代表实体的完整状态。关闭延迟加载和传递不完整的实体图很容易导致错误,因为接受实体引用并面对 null/empty 引用的方法将不知道该引用是未加载还是不存在的区别.
[Serializable]
public class CountryViewModel
{
public int CountryID { get; set; }
public string CountryName { get; set; }
public IEnumerable<StateViewModel> States { get; set; } = new List<StateViewModel>();
}
[Serializable]
public class StateViewModel
{
public int StateID { get; set; }
public string StateName { get; set; }
}
然后在获取国家和州时:
var countries = await _context.Countries
.Select(x => new CountryViewModel
{
CountryId = x.CountryId,
CountryName = x.Name,
States = x.States.Select(s => new StateViewModel
{
StateId = s.StateId,
StateName = s.Name
}).ToList()
}).ToListAsync(cancellationToken);
利用 Automapper,这可以很容易地简化为:
var countries = await _context.Countries
.ProjectTo<CountryViewModel>()
.ToListAsync(cancellationToken);