在 C# 代码中的 DB 中的 Linq 查询中包含空单元格
Posted
技术标签:
【中文标题】在 C# 代码中的 DB 中的 Linq 查询中包含空单元格【英文标题】:Include null cells in Linq query from DB in C# code 【发布时间】:2021-11-23 03:03:04 【问题描述】:我只想知道是否仍然可以从 linq 查询中检索空单元格,因为即使单元格为“空”,我也需要这些行。
上下文是我有一个基于客户合同的版本控制,我更新他们的应用程序并使用最新版本构建和更新日期更新数据库。此报告返回所有合同及其最新更新构建和每个合同的更新日期。
我在 SQL 中有这个查询,用于生成报告:
SELECT c.contrato, b.build, MAX(p.data_atualizacao) AS [data_atualizacao]
FROM
(
SELECT id_contrato, MAX(id_build_verus) AS id_build_verus FROM tbl_controle_atualizacao_contrato
GROUP BY id_contrato
) d
JOIN tbl_controle_atualizacao_contrato P ON p.id_contrato = d.id_contrato AND p.id_build_verus = d.id_build_verus
RIGHT JOIN tbl_contrato c WITH(NOLOCK) ON p.id_contrato = c.id_contrato
LEFT JOIN tbl_build_verus b WITH(NOLOCK) ON p.id_build_verus = b.id_build_verus
WHERE c.contrato <> 0 AND c.id_empresa = 1 AND c.ativo = 1
GROUP BY c.contrato, b.build
输出是这样的:
然后在我的代码中,我设置了一个 linq 表达式,它为我返回一个具有相同结果的查询:
var listaTotalContratos = db.tbl_controle_atualizacao_contrato.Include(i => i.tbl_contrato).OrderByDescending(d => d.data_atualizacao).ThenByDescending(b => b.tbl_build_verus.build)
.Where(c => c.tbl_contrato.contrato != 0 && c.tbl_contrato.ativo == true && c.tbl_contrato.id_empresa == 1)
.Select(r => new
contrato = r.tbl_contrato.contrato.ToString(),
UF = r.tbl_contrato.tbl_cliente.tbl_pessoa.tbl_endereco.FirstOrDefault().uf,
build = r.tbl_build_verus.build,
data_atualizacao = r.tbl_contrato.tbl_controle_atualizacao_contrato.Max(x => x.data_atualizacao)
).GroupBy(c => c.contrato).Select(s => new contrato = s.Key, listaItens = s.ToList() ).ToList();
我进行了自定义选择以从单元格中获取值,因为我得到了重复的结果。
linq 代码有效,但我认为它忽略了带有空单元格的行。
谢谢!
【问题讨论】:
在 SQL 查询中,您在 tbl_build_verus 上执行 LEFT JOIN,而 linq 查询中不存在,这就是它忽略空字段的原因。您需要将确切的查询转换为 linq 查询,其中包含 LEFT JOIN,否则它将执行正常的 JOIN。您可以使用一些适配器来查看 linq 正在生成什么 SQL 查询以及您的错误在哪里。 【参考方案1】:在 SQL 查询中,您在 tbl_build_verus 上执行 LEFT JOIN,而 linq 查询中不存在,这就是它忽略空字段的原因。您需要将确切的查询转换为 linq 查询,其中包含 LEFT JOIN,否则它将执行正常的 JOIN。
你的结果应该是这样的:
var query =
from d in tbl_controle_atualizacao_contrato
join p in tbl_controle_atualizacao_contrato
on p.id_contrato = d.id_contrato
AND p.id_build_verus = d.id_build_verus
join c in tbl_contrato
on p.id_contrato = c.id_contrato
left join b in tbl_build_verus
ON p.id_build_verus = b.id_build_verus
select new
c.contrato,
b.build,
data_atualizacao = MAX(p.data_atualizacao)
where c.contrato <> 0 AND c.id_empresa = 1 AND c.ativo = 1
GROUP BY c.contrato, b.build;
我建议在您的开发环境中使用某种类型的拦截器/分析器,这样您就可以实时查看 EF 正在执行的查询。见this
拦截器示例:
public class CommandInterceptor : DbCommandInterceptor
public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)
Debug.WriteLine(command.CommandText);
return base.DataReaderDisposing(command, eventData, result);
public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)
Debug.WriteLine(command.CommandText);
return base.NonQueryExecuted(command, eventData, result);
public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)
Debug.WriteLine(command.CommandText);
return base.ReaderExecuted(command, eventData, result);
public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)
Debug.WriteLine(command.CommandText);
return base.ScalarExecuted(command, eventData, result);
拦截器注册
services.AddDbContext<Context>(contextOptions =>
contextOptions
.AddInterceptors(new CommandInterceptor())
);
【讨论】:
很好的解释!我没有考虑连接问题,因为我认为导航正在通过 linq 表达式进行所有连接......我将尝试这种方法并检查这个拦截器机制。非常感谢朋友!以上是关于在 C# 代码中的 DB 中的 Linq 查询中包含空单元格的主要内容,如果未能解决你的问题,请参考以下文章
LINQ to SQL 可以查询 XML 字段 DB-serverside 吗?