EF Core 6:使用 SqlParameters 为插值存储过程生成错误的 SQL

EF Core 6 Generating faulty SQL for interpolated stored procedures using SqlParameters

提问人:MaxTheCoder 提问时间:2/22/2022 最后编辑:marc_sMaxTheCoder 更新时间:2/25/2022 访问量:177

问:

我有一个包含多个参数的 SQL Server 存储过程

ALTER PROCEDURE [dbo].[BUP_BankUpload]
    @SPP_ProcessID uniqueidentifier,  
    @SPP_FileName NVARCHAR(250) = '',  
    @SPP_UploadInputType int,   
    @SPP_UploadOutputType int,  
    @SPP_CheckPreviousProcessing bit = 0,  
    @SPP_BankPeriod NVARCHAR(100) = '',  
    @SPP_BankName NVARCHAR(50) = 'Option' 

我使用 EF Core 6 和插值查询调用它:SqlParameter

    SqlParameter[] sqlParams =
    {
          new SqlParameter("SPP_ProcessID", SqlDbType.UniqueIdentifier) { Value = Guid.NewGuid() },
          new SqlParameter("SPP_FileName", SqlDbType.NVarChar) { Value = bankFileName },
          new SqlParameter("SPP_UploadInputType", SqlDbType.Int) { Value = 1 },
          new SqlParameter("SPP_UploadOutputType", SqlDbType.Int) { Value = 1 },
          new SqlParameter("SPP_CheckPreviousProcessing", SqlDbType.Bit) { Value = true },
          new SqlParameter("SPP_BankPeriod", SqlDbType.NVarChar) { Value = bankPeriod != null ? bankPeriod : "None"},
          new SqlParameter("SPP_BankName", SqlDbType.NVarChar) { Value = bankName}
    };

List<BankUploadModel>  BankUploadSQL = applicationDbContext.BankUpload.FromSqlInterpolated($"BUP_BankUpload {sqlParams[0]}, {sqlParams[1]}, {sqlParams[2]}, {sqlParams[3]}, {sqlParams[4]}, {sqlParams[5]}, {sqlParams[6]}").ToList();

这将生成以下 SQL:

exec sp_executesql N'BUP_BankUpload @SPP_ProcessID, @SPP_FileName, @SPP_UploadInputType, 
@SPP_UploadOutputType, @SPP_CheckPreviousProcessing, @SPP_BankPeriod, @SPP_BankName',
N'@SPP_ProcessID uniqueidentifier,@SPP_FileName nvarchar(65),@SPP_UploadInputType int,@SPP_UploadOutputType int,
@SPP_CheckPreviousProcessing bit,@SPP_BankPeriod nvarchar(4),@SPP_BankName nvarchar(5)',
@SPP_ProcessID='87DD543E-64F1-4C7A-A35B-82441B034B15',
@SPP_FileName=N'Processed_txns20060198-29Jan2022-05Feb2022_Final_(01-02-2022).csv',
@SPP_UploadInputType=1,
@SPP_UploadOutputType=1,
@SPP_CheckPreviousProcessing=1,
@SPP_BankPeriod=N'None',
@SPP_BankName=N'Bank1'

运行时,会引发以下错误:

消息 8114,级别 16,状态 1,过程 BUP_BankUpload,第 0 行 [批处理开始行 0]
将数据类型 nvarchar 转换为日期时出错。

这是不可能的,因为存储过程中没有字符串到日期的转换。

当我通过删除参数化元数据来修改 SQL 语句时,如下所示:

exec sp_executesql N'BUP_BankUpload 
@SPP_ProcessID=''87DD543E-64F1-4C7A-A35B-82441B034B15'',
@SPP_FileName=N''Processed_txns20060198-29Jan2022-05Feb2022_Final_(01-02-2022).csv'',
@SPP_UploadInputType=1,
@SPP_UploadOutputType=1,
@SPP_CheckPreviousProcessing=1,
@SPP_BankPeriod=N''None'',
@SPP_BankName=N''Bank1'''

使用相同的参数,它可以正常工作。

谁能给我指出正确的方向,看看这里发生了什么?

SQL SQL Server 实体框架 存储过程 传递

评论

1赞 David Browne - Microsoft 2/22/2022
这些调用是等效的,并且没有日期时间参数。错误来自存储过程内部,可能是执行计划差异或影响日期格式的会话语言差异。
0赞 Jeroen Mostert 2/22/2022
当你消除了不可能的事情时,剩下的一切,无论多么不可能,都必须是真理。如果 SQL Server 在执行 sproc 时告诉您转换失败,那么很可能转换失败,而您还没有说服我这是不可能的。还要考虑隐式转换(例如从一个表复制到另一个表)。虽然没有明显的机制来解释为什么不同的调用会暴露问题,但这是次要问题。先调试失败的调用,然后再继续。datedate
0赞 MaxTheCoder 2/22/2022
没有日期转换。如果我删除存储过程的全部内容并留下打印语句,则会出现相同的错误。
0赞 MaxTheCoder 2/22/2022
此外,调用不能等同于一个工作,一个不工作。
0赞 Charlieface 2/22/2022
如果它不能解决这个错误,我建议你按名称而不是位置传递参数,至少它可以防止以后的开发人员不可避免地重写过程时出现未来的错误$"BUP_BankUpload @SPP_ProcessID={sqlParams[0]}, @SPP_FileName={sqlParams[1]},

答: 暂无答案