【发布时间】:2018-05-11 06:56:52
【问题描述】:
我正在尝试在 .Net Core 中使用以下代码执行 SP
using (DBContext context = new DBContext()){
{
using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "Sp_Name";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@input", SqlDbType.VarChar ,3) { Value = InputValue });
command.Parameters.Add(new SqlParameter("@Return_Value", SqlDbType.VarChar, 3) { Value = string.Empty });
context.Database.OpenConnection();
var dataReader = command.ExecuteReader();
if (dataReader.Read())
{
var code = dataReader.GetString(dataReader.GetOrdinal(""));
}
}}
查询对某些输入参数工作正常,但对某些输入参数抛出异常,例如:
--此场景在 EF 代码和 SQL 中运行良好
SP - exec Sp_Name @input = 'PDX', @Return_Value = ''
--Result (No Column Name) - '3I9'
-- 这种情况在 EF 代码中不工作,但在 SQL 中工作正常
SP - exec Sp_Name @input = 'N01', @Return_Value = ''
--Result (No Column Name) - 'WE5'
异常信息
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
at Mednax.ReferringPhysician.Data.PdxService.getGPMSCode(String practiceCode) in C:\Work\GIT\ReferringPhysician2\Mednax.ReferringPhysician.WebAPI\Mednax.ReferringPhysician.Data\PdxService.cs:line 971
ClientConnectionId:199f2b1a-cb1b-4752-8632-9f2c54bcefd8
Error Number:-2,State:0,Class:11
堆栈跟踪:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
SP 如下所示:
SP -
(
@Input varchar(3),
@Return_Value varchar(3) output
)
AS
SET NOCOUNT ON
SET @Return_Value = NULL
SELECT TOP 1 @Return_Value = pacl.P_Code
FROM TABLEA pacl with (nolock)
LEFT OUTER JOIN TABLEB rpp with (nolock)
ON rpp.Code = pacl.Code
AND rpp.P_Code = @Input
WHERE rpp.P_Code IS NULL
ORDER BY pacl.P_Code
IF @@Rowcount = 0 SET @Return_Value = '***'
Select @Return_Value
异常消息的 Targetsite 内部详细信息:
【问题讨论】:
-
我强烈建议将错误消息和完整的堆栈跟踪作为文本而不是图像发布。另外,如果您知道只有一列,为什么不直接使用
deatReader.GetString(0)? -
哪一行失败了?你至少能告诉我们吗?另外:由于此代码看起来不涉及 EF...如果您只使用
SqlConnection是否有效? -
您好,感谢您的评论,我已添加堆栈跟踪详细信息
-
@PradeepH 听起来像“参数嗅探”,然后 - 严重偏差数据的常见问题。我们能不能看到SP?另外,请注意,有一些
SET选项(默认情况下)在 .NET 和 SSMS 之间是不同的 - 如果SET选项导致索引不可用,这可能会导致性能巨大差异.例如,“持久计算列”可能非常容易受到此问题的影响。 -
对。所以第一个也是最简单的尝试是参数嗅探修复。尝试将
OPTION ( OPTIMIZE FOR UNKNOWN )添加到select主查询的底部(真正起作用的查询,而不是最后的查询),在order by之后。看看有没有帮助。