我遇到一个完全未使用的变量导致错误的情况。删除未使用的变量声明会清除错误。清除后,错误将保持清除(即使未使用的变量已恢复),直到SQL Server重新启动,此时它将返回。
我已经定义了一个CLR函数和一个表值UDF。我可以使用这个测试用例代码调用CLR:
Declare @name_does_not_matter Table (any_column_name int);
Select dbo.MapTesseractUris(
N'<a href="tesseract:2">map this uri</a>',
N'localhost:6313');
这样做会导致此错误:
A .NET Framework error occurred during execution of user-defined routine or aggregate "MapTesseractUris":
System.Data.SqlClient.SqlException:
System.Data.SqlClient.SqlException:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlCommand.SetUpSmiRequest(SqlInternalConnectionSmi innerConnection)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderSmi(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at Tesseract.Database.TesseractUri.MapPageIdsToUrls(IEnumerable`1 pageIds, String forDomain)
at Tesseract.Database.TesseractUri.MapTesseractUris(String html, String forDomain)
错误发生在我的代码中CLR调用UDF的位置。直接调用UDF不会导致错误。
但是,如果我使用此代码调用CLR,我会得到正确的预期结果:
Select dbo.MapTesseractUris(
N'<a href="tesseract:2">map this uri</a>',
N'localhost:6313');
一旦我成功执行,进一步的执行将始终正常运行。我可以恢复丢失的Declare
语句,但不会出错。我可以改变输入参数而不是错误。
我可以通过重新启动SQL Server或删除并重新部署整个数据库来导致错误返回。
如果不明显,@name_does_not_matter
表变量不会在任何地方使用。这必须是导致问题的表变量(Declare @name_does_not_matter int
不会导致问题)。
导致这种情况的原因是什么?
如何解决这个问题,而不是每次SQL Server重新启动时都执行“修复”SQL?
更新
以下是Tesseract.Database.TesseractUri.MapPageIdsToUrls
的请求代码:
private static IDictionary<int, string> MapPageIdsToUrls(
IEnumerable<int> pageIds,
string forDomain)
{
using (var db = new SqlConnection("context connection=true")) {
db.Open();
using (var cmd = db.CreateCommand()) {
cmd.CommandType = CommandType.Text;
cmd.CommandText = @"
Select [Id], [Url]
From [dbo].[ResolvePageUrls](@pageIds, @domain)";
var p = cmd.Parameters.AddWithValue(
"@pageIds",
CreateDataRecords(pageIds));
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "dbo.IntTable";
cmd.Parameters
.Add("@domain", SqlDbType.NVarChar, 252)
.Value = forDomain;
using (var reader = cmd.ExecuteReader()) {
return reader.OfType<IDataRecord>()
.Select(row => Tuple.Create(
row.GetInt32(0),
row.GetValue(1) as string))
.ToDictionary(t => t.Item1, t => t.Item2);
}
}
}
}
private static IEnumerable<SqlDataRecord> CreateDataRecords(
IEnumerable<int> ids)
{
var metaData = new[] { new SqlMetaData("Value", SqlDbType.Int) };
var record = new SqlDataRecord(metaData);
foreach (var id in ids.Distinct()) {
record.SetInt32(0, id);
yield return record;
}
}