如何在 EF Core 5 中从一对一和一对多关系中获取数据
how to get data from a one to one and one to many relationship in EF Core 5
我有这个型号
在我的数据库中,当我通过 Organismo 过滤 Ofertas 时,我得到了这些结果
我在哪里看到 id=6 的有机体有 2 个不同的 Ofertas
当我在我的 Web 中将此查询翻译成 EF 时 API
// GET: api/Ofertas/organismo/vasco
[HttpGet("organismo/{organismoId}")]
public IEnumerable<Oferta> GetOfertasByOrganismo(int organismoId)
{
var result = _context.Ofertas.Include(o => o.Concurso).ThenInclude(c
=> c.Organismo).Where(o => o.Concurso.Organismo.Id ==
organismoId).ToList();
return result;
然后我发起这个请求 http://localhost:5000/api/ofertas/organismo/6
我得到这些结果
result
Count = 1
[0]: {Boletus_back_end.Domain.Oferta}
也就是只有一个Oferta
在我的 Web 中 API 我的 Db 上下文已断开连接
services.AddDbContext<BoletusContext>(opt=>
opt.UseSqlServer(Configuration.GetConnectionString("BoletusConexion"))
.EnableSensitiveDataLogging()
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
关于如何获得所有相关的 Ofertas 的任何想法?
谢谢
您可能需要 post 代码,但当项目禁用延迟加载然后尝试查询尚未加载请求的相关数据或已加载该数据的物化实体时,通常会出现此问题急切且相关实体是可选的。
例如,像这样:
var results = context.Ofertas.AsNoTracking().ToList();
var test = results.Where(x => x.Concurso.Organismo.Id == 1).ToList();
这里的问题是我们没有在原始查询中获取 Ofertas 的 Concursos 或 Oransimos,我们已经通过第一个 ToList
调用实现了结果。解决方案是确保我们将 Where
条件放在可以集成到查询中的某个地方,或者我们确保我们渴望加载所有相关数据,我们还确保 optional/null 引用被考虑在内:
a) 在查询中:
var results = context.Ofertas.AsNoTracking()
.Where(x => x.Concurso.Organismo.Id == 1).ToList();
这将通过,因为我们的查询将查找和 return 具有所需 Organismo ID 的 Ofertas,即使数据中的关系是可选的。但是,它不会急于用 Ofertas returned 加载 Concurso 或 Organismo。这些引用仍然可以为空。
b) 预先加载相关数据并检查#Null:
var results = context.Ofertas
.Include(x => x.Concurso)
.ThenInclude(x => x.Organismo)
.AsNoTracking()
.ToList();
var test = results.Where(x => x.Concurso?.Organismo?.Id == 1).ToList();
// or
var test = results.Where(x => x.Concuso != null
&& x.Concurso.Organismo != null
&& x.Concurso.Organismo.Id == 1).ToList();
与原始查询一样,此查询预取所有 Ofertas,但预先加载所有相关数据。只需要进行 null 检查 if/when 关系可以为 NULL。如果需要关系并预先加载,则不需要空检查,但它要求数据要么预先加载,要么能够延迟加载。
有趣的是 EF 将填充相关实体 if/where 这些实体已经被跟踪。因此,例如,如果之前有任何内容加载了第一个 Oferta 结果引用的一个或多个 Concurso,以及 Organismo ID #1,那么这些引用将存在于 returned 查询数据中。在这种情况下,我将急于用 Oferta 加载 Concursos,但只预取 Organismo #1:
var organismo = context.Organismos.Single(x => x.Id == 1);
// The DbContext is now tracking this entity, we do nothing with this instance.
var results = context.Ofertas.Include(x => x.Concurso).AsNoTracking.ToList();
var test = results[0].Concurso.Organismo.Id == 1; // Passes in our case.
var test2 = results.Where(x => x.Concurso.Organismo.Id == 1).ToList(); // can still fail!
第一个测试将通过,因为当我们从 DbContext 加载 Ofertas 时,该上下文已经在跟踪 Organismo #1,因此即使我们不急于加载 organismos,它也会预先填充。然而,除非所有引用恰好都是#1,否则 Organismo 引用的其余部分将为空,第二个测试将继续失败。
对不起
问题出在 Concursos 中的数据 Table 缺少将 Ofertra 与 Concurso 相关的记录
现在一切正常
test
Count = 2
[0]: {Boletus_back_end.Domain.Oferta}
[1]: {Boletus_back_end.Domain.Oferta}
谢谢
我有这个型号
在我的数据库中,当我通过 Organismo 过滤 Ofertas 时,我得到了这些结果
我在哪里看到 id=6 的有机体有 2 个不同的 Ofertas
当我在我的 Web 中将此查询翻译成 EF 时 API
// GET: api/Ofertas/organismo/vasco
[HttpGet("organismo/{organismoId}")]
public IEnumerable<Oferta> GetOfertasByOrganismo(int organismoId)
{
var result = _context.Ofertas.Include(o => o.Concurso).ThenInclude(c
=> c.Organismo).Where(o => o.Concurso.Organismo.Id ==
organismoId).ToList();
return result;
然后我发起这个请求 http://localhost:5000/api/ofertas/organismo/6
我得到这些结果
result
Count = 1
[0]: {Boletus_back_end.Domain.Oferta}
也就是只有一个Oferta
在我的 Web 中 API 我的 Db 上下文已断开连接
services.AddDbContext<BoletusContext>(opt=>
opt.UseSqlServer(Configuration.GetConnectionString("BoletusConexion"))
.EnableSensitiveDataLogging()
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
关于如何获得所有相关的 Ofertas 的任何想法?
谢谢
您可能需要 post 代码,但当项目禁用延迟加载然后尝试查询尚未加载请求的相关数据或已加载该数据的物化实体时,通常会出现此问题急切且相关实体是可选的。
例如,像这样:
var results = context.Ofertas.AsNoTracking().ToList();
var test = results.Where(x => x.Concurso.Organismo.Id == 1).ToList();
这里的问题是我们没有在原始查询中获取 Ofertas 的 Concursos 或 Oransimos,我们已经通过第一个 ToList
调用实现了结果。解决方案是确保我们将 Where
条件放在可以集成到查询中的某个地方,或者我们确保我们渴望加载所有相关数据,我们还确保 optional/null 引用被考虑在内:
a) 在查询中:
var results = context.Ofertas.AsNoTracking()
.Where(x => x.Concurso.Organismo.Id == 1).ToList();
这将通过,因为我们的查询将查找和 return 具有所需 Organismo ID 的 Ofertas,即使数据中的关系是可选的。但是,它不会急于用 Ofertas returned 加载 Concurso 或 Organismo。这些引用仍然可以为空。
b) 预先加载相关数据并检查#Null:
var results = context.Ofertas
.Include(x => x.Concurso)
.ThenInclude(x => x.Organismo)
.AsNoTracking()
.ToList();
var test = results.Where(x => x.Concurso?.Organismo?.Id == 1).ToList();
// or
var test = results.Where(x => x.Concuso != null
&& x.Concurso.Organismo != null
&& x.Concurso.Organismo.Id == 1).ToList();
与原始查询一样,此查询预取所有 Ofertas,但预先加载所有相关数据。只需要进行 null 检查 if/when 关系可以为 NULL。如果需要关系并预先加载,则不需要空检查,但它要求数据要么预先加载,要么能够延迟加载。
有趣的是 EF 将填充相关实体 if/where 这些实体已经被跟踪。因此,例如,如果之前有任何内容加载了第一个 Oferta 结果引用的一个或多个 Concurso,以及 Organismo ID #1,那么这些引用将存在于 returned 查询数据中。在这种情况下,我将急于用 Oferta 加载 Concursos,但只预取 Organismo #1:
var organismo = context.Organismos.Single(x => x.Id == 1);
// The DbContext is now tracking this entity, we do nothing with this instance.
var results = context.Ofertas.Include(x => x.Concurso).AsNoTracking.ToList();
var test = results[0].Concurso.Organismo.Id == 1; // Passes in our case.
var test2 = results.Where(x => x.Concurso.Organismo.Id == 1).ToList(); // can still fail!
第一个测试将通过,因为当我们从 DbContext 加载 Ofertas 时,该上下文已经在跟踪 Organismo #1,因此即使我们不急于加载 organismos,它也会预先填充。然而,除非所有引用恰好都是#1,否则 Organismo 引用的其余部分将为空,第二个测试将继续失败。
对不起
问题出在 Concursos 中的数据 Table 缺少将 Ofertra 与 Concurso 相关的记录
现在一切正常
test
Count = 2
[0]: {Boletus_back_end.Domain.Oferta}
[1]: {Boletus_back_end.Domain.Oferta}
谢谢