【发布时间】:2017-12-05 16:25:07
【问题描述】:
我正在尝试创建一个 SQL CLR 存储过程,它将创建一个表,将表名传递给一个服务,该服务将向其中批量插入一些数据,显示表的结果,然后清理表。
到目前为止我已经尝试过:
-
使用
SqlTransaction。取消事务有效,但它使我的查询窗口进入我无法继续处理它的状态。此会话中活动的事务已被另一个会话提交或中止
-
使用
TransactionScope。与 1 相同的问题。 -
通过发出
DROP TABLESqlCommand在finally子句中手动清理表。这似乎没有运行,尽管在发出命令之前我的SqlContext.Pipe.Send()运行。它似乎与任何时间限制无关,因为如果我在打印另一行之前发出Thread.Sleep(2000),它仍然会打印第二行,而command.ExecuteNonQuery()会在打印第二行之前停止。 -
将手动清理代码放入 CER 或
SafeHandle。这不起作用,因为拥有 CER 需要一些保证,包括不分配额外的内存或调用未用ReliabilityContract修饰的方法。
我在这里遗漏了一些明显的东西吗?如何处理用户取消查询?
编辑:每个场景的代码都有多次迭代,但采取的一般行动如下:
[SqlProcedure]
public static void GetData(SqlString code)
{
Guid guid = Guid.NewGuid();
using (var connection = new SqlConnection("context connection=true"))
{
connection.Open();
try
{
SqlContext.Pipe?.Send("Constrain");
SqlCommand command1 = new SqlCommand($"CREATE TABLE qb.{code}_{guid:N} (Id INT)", connection);
command1.ExecuteNonQuery();
SqlContext.Pipe?.Send($"Create: qb.{code}_{guid:N}");
//emulate service call
Thread.Sleep(TimeSpan.FromSeconds(10));
SqlContext.Pipe?.Send($"Done: qb.{code}_{guid:N}");
}
finally
{
SqlContext.Pipe?.Send("1");
//drop table here instead of sleep
Thread.Sleep(2000);
SqlContext.Pipe?.Send("2");
}
}
}
【问题讨论】:
-
添加相关代码部分
-
一个简单的答案是如果用户取消查询然后立即删除表。该服务在执行工作之前首先测试该表是否存在,如果不存在,则假定用户取消了查询,因此它什么也不做。
-
@Rob 问题是在用户取消查询后删除表。
finally块不会像尝试 3 中提到的那样执行DROP TABLE。 -
带有查询窗口的部分在哪里?
-
@SirRufo 我没有包括它,因为它只是一个电话
EXEC clrproc 'parameter'
标签: c# sql-server sqlclr