对于某些数据库SQL Server 2012 和 2019上的简单选择查询,有时 Dapper 或 System.Data 不会返回正确的结果

问题描述

我有一个简单的查询,它在托管于 信息系统。问题是对于某些数据库(通常是大小大于 10-20GB 的数据库),当结果应该为真时,查询返回假。数据库一个版本中是 sql Server 2012,在另一个版本中是 2019。但在这两个奇怪的行为发生。我的 ORM 是最新版本的 Dapper。查询是这样的:

SELECT 
    CASE Column
        WHEN 'S' THEN 1
        ELSE 0
    END AS Result
FROM 
    Table
WHERE 
    Id = @Id

该列的类型为 CHAR(1)。在 C# 中,我们有以下代码

bool result= Context.Connection.QueryFirstOrDefault<bool>(
    sql: QUERY,param: new { Id = id },transaction: Context.Transaction
);

我已经检查了一些简单的东西,比如连接字符串,以及是否存在带有 Id 参数值的寄存器。

在两个数据库中运行 sql Profiler 我能够捕获 dapper 为数据库发送的查询

exec sp_executesql N'
SELECT 
    CASE Column
        WHEN ''S'' THEN 1
        ELSE 0
    END AS Result
FROM 
    Table
WHERE 
    Id = @Id',N'@Id int',@Id=103051026

在 SSMS 2019 中运行相同的查询,结果如预期的那样为真,但在生产和开发环境中的应用程序中,某些数据库的结果有时为假。当在单次运行中结果碰巧为 false 时,对于批处理中方法的所有调用,它将为 false(对于这里的批处理,您可以理解为在 Web Api 中对表中的数千个寄存器执行操作)。

有人可以帮我解决这种奇怪的行为吗?

在@Charliface 的评论之后,我收到了异常:

"ERRO" "System.ArgumentNullException: Value cannot be null. (Parameter 'value')
   at Dapper.sqlMapper.ReadChar(Object value) in C:\projects\dapper\Dapper\sqlMapper.cs:line 1878
   at Dapper.sqlMapper.<>c__displayClass198_0.<GetStructDeserializer>b__0(IDataReader r) in C:\projects\dapper\Dapper\sqlMapper.cs:line 2914
   at Dapper.sqlMapper.QueryRowImpl[T](IDbConnection cnn,Row row,CommandDeFinition& command,Type effectiveType) in C:\projects\dapper\Dapper\sqlMapper.cs:line 1199
   at Dapper.sqlMapper.QueryFirstOrDefault[T](IDbConnection cnn,String sql,Object param,IDbTransaction transaction,Nullable`1 commandTimeout,Nullable`1 commandType) in C:\projects\dapper\Dapper\sqlMapper.cs:line 763
   at ProjectNamespace.Repository.RunSimpleQuerz(Nullable`1 codigoTraco,Int32 implantacaoId) in C:\agents\1\_work\113\s\src\Repositorios\Siac\Repository.cs:line 26
   at ProjectNamespace.Service.Business.Method5(Evento evento,Rule regraValida,DateTime dataExecucao) in C:\agents\1\_work\113\s\src\Servicos\Something\Servico\Business.cs:line 278
   at ProjectNamespace.Service.Business.Method4(Evento evento,Dto dto,RegraInteligenciaTecnologica regraCorrente,Nullable`1 codigoTracoCorrente,Int32 anoCorrente,Int32 semanaCorrente,Int32 quatidadeSemanasPeriodo,List`1 list,DateTime dataExecucao) in C:\agents\1\_work\113\s\src\Servicos\Something\Servico\Business.cs:line 100
   at ProjectNamespace.Service.Business.Method3(List`1 listaEventos,DateTime dataExecucao) in C:\agents\1\_work\113\s\src\Servicos\Something\Servico\Business.cs:line 64
   at ProjectNamespace.Service.Business.Method2(Int32 implantacaoId,DateTime dataInicio,DateTime dataExecucao) in C:\agents\1\_work\113\s\src\Servicos\Something\Servico\Business.cs:line 35
   at ProjectNamespace.Service.Business.Method1(Int32 implantacaoId,DateTime dataInicioOperacao,DateTime dataMemoria,Nullable`1 Avaliacao) in C:\agents\1\_work\113\s\src\Servicos\Something\Servico\GerenciadorServico.cs:line 259" "MOTOR" 26

解决方法

ADO.NET 和 Dapper 都只是按照提供的方式执行查询;他们无法决定会发生什么,因此:我可以在这里看到两种可能性:1) 查询是正确的,并且对于 某个时间间隔,结果不是您所期望的是,但是因为数据不是您期望的那样,或者 2) 您正在从多个线程访问 Context.Connection(对于同一个连接),这可能导致未定义的行为包括从并发操作中获取混乱的查询结果

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...