我正在尝试使用存储过程从 SQL Server 2008 R2 数据库中查询数据。代码执行时没有错误,但查询不会返回任何结果。当使用完全相同的参数通过 SQL Server Management Studio 调用相同的存储过程时,将正确返回数据。我不知道是什么原因导致这种情况,可能是 SqlClient 实现的特定原因?查询返回两个DateTime2
值之间的所有数据;如果我使这些DateTime2
值相距足够远,则返回数据。显然,这不是所需的行为。
C# 代码(在这种情况下,startTime.HasValue
和 endTime.HasValue
是正确的):
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
SqlCommand comm = conn.CreateCommand();
comm.CommandType = CommandType.StoredProcedure;
comm.CommandText = "GetAllPropertyValues";
comm.Parameters.Add("@dataTypeName", SqlDbType.NVarChar).Value = dataTypeName;
comm.Parameters.Add("@propertyName", SqlDbType.NVarChar).Value = propertyName;
if (startTime.HasValue)
{
var startString = startTime.Value.ToUniversalTime().ToString("O");
if (endTime.HasValue)
{
var endString = endTime.Value.ToUniversalTime().ToString("O");
comm.CommandText += "Between";
comm.Parameters.Add("@startTime", SqlDbType.DateTime2).Value = startString;
comm.Parameters.Add("@endTime", SqlDbType.DateTime2).Value = endString;
}
else
{
comm.CommandText += "After";
comm.Parameters.Add("@dateTime", SqlDbType.DateTime2).Value = startString;
}
}
SqlDataReader reader = comm.ExecuteReader();
while (reader.Read())
{
// ...
}
SQL Server 存储过程:
declare @str varchar(max) = 'select * from [dbo].[' + @tableName + '] where StartTime BETWEEN ''' +
CAST(@startTime as nvarchar(max)) + ''' AND ''' + CAST(@endTime as nvarchar(max)) + ''' order by StartTime asc'
exec(@str)
执行的示例查询:
USE [Construct3]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[GetAllPropertyValuesBetween]
@datatypeName = N'HeadPose',
@propertyName = N'HeadRotationRadiansZ',
@startTime = '2014-12-31T19:00:00.0000000Z',
@endTime = '2014-12-31T20:00:00.0000000Z'
SELECT 'Return Value' = @return_value
GO
假设存储过程中的@startTime
和@endTime
参数是类型 DATETIME
,则执行从日期时间到字符串的双重转换,首先在 C# 代码上执行此操作:
var startString = startTime.Value.ToUniversalTime().ToString("O"); //This will create the datetime as a string using .NET format
您将它传递给存储过程,如下所示DateTime2
:
comm.Parameters.Add("@startTime", SqlDbType.DateTime2).Value = startString;
然后你在SQL上将其转换回字符串格式:
CAST(@startTime as nvarchar(max))
这可能是问题所在,当您在 .NET 和 SQL 中从DATETIME
转换为字符串时,不希望它们具有相同的结果,因此当您在数据库上执行存储过程时,您会得到结果,但是当您从 .NET 调用它时,由于日期错误,因此没有结果。我建议将这些日期参数的值作为普通的 .NET DateTime
值传递,并将其转换为存储过程中的varchar
值。您可以使用 SQL 中的CONVERT
函数来实现这一点,请查看此链接以获取有关CONVERT
日期格式的更多信息。
希望这有帮助。
更改 CommandText
属性将清除Parameters
集合。完成文本后设置所有参数。
此外,您拥有的东西将容易受到SQL注入攻击。你应该使用 sp_executesql
而不是 exec()
,以便安全地处理时间参数。我将为您提供一个怀疑的好处,即 @tableName
参数不是用户可以输入任意文本的东西,而是必须从服务器验证的表列表中进行选择。