【问题标题】:replace joins with navigation properties用导航属性替换连接
【发布时间】:2020-12-13 10:35:41
【问题描述】:

根据这里人们的建议,我正在尝试使用导航属性重写下面的 linq 查询。

我还没有走多远,因为我不确定如何用导航属性替换我的 Linq 查询中的联接。

到目前为止,我有这个:

await _context.StarList(sl => new 
{
    sl.StarId,
    sl.StarType,
    sl.StarTitle,
    sl.ChemicalId...
}

但是,在原始查询中,我开始在查询中使用“化学原子”。

所以我不确定如何过渡到他们。

所以我的问题是,如何将原始查询中的联接替换为导航属性?

谢谢!

 public async Task<ActionResult<object>> GetStarChemicalData(string starID)
    {
        var starChemicalData = await (from starlist in _context.StarList
                                      join ql in _context.ChemicalList on starlist.ChemicalId equals ql.ChemicalId into stars
                                      from chemicallist in stars.DefaultIfEmpty()
                                      join qc in _context.ChemicalAtoms on chemicallist.ChemicalId equals qc.ChemicalId into chemicals
                                      from chemicalatoms in chemicals.DefaultIfEmpty()
                                      join nk in _context.StarLinks on chemicalatoms.AtomId equals nk.AtomId into links
                                      from starlinks in links.DefaultIfEmpty()
                                      where starlist.StarId == starID
                                      select new
                                      {
                                          StarId = starlist.StarId,
                                          StarType = starlist.StarType,
                                          StarTitle = starlist.StarTitle,
                                          ChemicalId = starlist.ChemicalId,
                                          AtomId = (Guid?)chemicalatoms.AtomId,
                                          OrderId = chemicalatoms.OrderId,
                                          ChemicalText = chemicallist.ChemicalText,
                                          AtomText = chemicalatoms.AtomText,
                                          Wavelength = chemicalatoms.Wavelength,
                                          isRedShifted = (starlinks.AtomId != null && starlist.StarType == 1) ? 1
                                          : (starlinks.AtomId == null && starlist.StarType == 1) ? 0
                                          : (int?)null
                                      })
                                          .GroupBy(x => x.StarId)
                                          .Select(g => new
                                          {
                                              StarId = g.FirstOrDefault().StarId,
                                              StarType = g.FirstOrDefault().StarType,
                                              StarTitle = g.FirstOrDefault().StarTitle,
                                              ChemicalId = g.FirstOrDefault().ChemicalId,
                                              ChemicalText = g.FirstOrDefault().ChemicalText,
                                              ChemicalAtoms = (g.FirstOrDefault().AtomId != null ? g.Select(x => new
                                              {
                                                  AtomId = x.AtomId,
                                                  OrderId = x.OrderId,
                                                  AtomText = x.AtomText,
                                                  Feedback = x.Wavelength,
                                                  IsCorrect = x.isRedShifted
                                              }) : null)
                                          }).FirstOrDefaultAsync();

        return starChemicalData;
        

【问题讨论】:

  • 你试过用Include()代替join吗?
  • @ArsenKhachaturyan 嗨,Linq 查询中会出现这种情况吗?
  • 更多信息请查看this帖子。
  • @ArsenKhachaturyan 所以不要像这样“加入”:from starlist in _context.StarList join ql in _context.ChemicalList,我会用 _context.StartList.Include("_context.ChemicalList") 替换它?谢谢!
  • 是的,就是这样,它会节省你的时间:)

标签: c# .net linq entity-framework-core


【解决方案1】:

根据上面的通信成功,我想我可以总结一下结果,这里)) 所以,不要这样:

var starChemicalData = await (from starlist in _context.StarList
    join ql in _context.ChemicalList on starlist.ChemicalId equals ql.ChemicalId into stars
    from chemicallist in stars.DefaultIfEmpty()
    join qc in _context.ChemicalAtoms on chemicallist.ChemicalId equals qc.ChemicalId into chemicals
    from chemicalatoms in chemicals.DefaultIfEmpty()
    join nk in _context.StarLinks on chemicalatoms.AtomId equals nk.AtomId into links 
    ...
    );

我们可以这样:

_context.StarList.Include(st => st.ChemicalList)
    .Include(ca => ca.ChemicalAtoms)  // or ThenInclude, based on your relations
    .Include(sl => sl.StartLinks)
    ...
    Select(r => new {...})
    ...

请注意,使用Include 时最重要的是您的关系(主外键)应该在您在此处使用的数据库表之间进行适当设置。

另一个重要的事情是,如果您的 PK⟶FK 关系中的一个包含 null 值,Include() 将不会带来行结果,而实际上它不应该。

【讨论】:

  • 哦,好吧,如果我想使用 Include(),我需要确保每个表都有一个主键,并且主键也是我想要包含的任何表中的外键?谢谢!例如,ChemicalList 的主键为 ChemicalId。哪个也是 StarList 中的外键?
  • 是的,这就是 EF 基本上是如何发挥作用的,否则,它将不知道 2 个表是如何连接的。在这些情况下,如果表没有正确设置关系,您可以使用 join(或者当您想在 SQL 中创建 LEFT OUTER JOIN 时),否则使用 Include 方法可以节省您的时间。跨度>
  • 但这并不能回答问题。 Include 是一个如何使用导航属性的例子。您没有回答如何将 LINQ join 语句转换为导航属性的问题。
  • 是的,我没有转换整个查询,但我想我已经展示了一个示例,说明如何使用带有Include 的导航属性来做到这一点(请查看上方)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
相关资源
最近更新 更多