使用 CLR 存储过程在事务中记录 TSQL
TSQL logging inside transaction using CLR stored procedure
我正在尝试将日志写入事务内的另一个数据库,这样即使事务被回滚,日志也会继续存在。我读过 this answer 上面写着:
One possibility is to use a CLR stored procedure to do the logging. This can open its own connection to the database outside the transaction and enter and commit the log data.
所以我使用 this article:
创建了 CLR 存储过程
[SqlProcedure]
public static void Voice(SqlString procedureName, SqlInt32 id)
{
Connection = new SqlConnectionStringBuilder();
Connection.ContextConnection = true;
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(Connection.ToString()))
{
conn.Open();
SqlCommand cmdInsert = conn.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("@id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = id;
cmdInsert.Parameters.Add("@procedureName", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = procedureName;
cmdInsert.ExecuteNonQuery();
}
transScope.Complete();
}
}
但是,在 SQL 服务器:
中执行并回滚存储过程后,数据未保存
BEGIN TRAN
EXEC dbo.SayHelloVoice @id = 1,
@procedureName = N'FooProcedure'
ROLLBACK TRAN
我们有三个环境:
dev
。服务器名称是 Q-SQL001
test
。服务器名称是 Q-SQL002
prod
。服务器名称是 Q-SQL003
所以这个 CLR 存储过程应该适用于所有环境。
你能说说我做错了什么吗?
任何帮助将不胜感激!
更新:
所以工作版是这样的。非常感谢 @Milney:
var serverName = string.Empty;
var dbName = string.Empty;
serverName = SqlExecuteScalar("SELECT @@SERVERNAME");
dbName = SqlExecuteScalar("SELECT DB_NAME()");
SqlConnectionStringBuilder sqlConn = new SqlConnectionStringBuilder();
sqlConn.InitialCatalog = dbName;
sqlConn.DataSource = serverName;
sqlConn.IntegratedSecurity = true;
sqlConn.ContextConnection = false;
sqlConn.Enlist = false;
sqlConn.ApplicationName = "New application";
var sql = "USE FooDatabase
INSERT INTO dbo.MyTable ..."
using (SqlConnection conn2 = new SqlConnection(sqlConn.ConnectionString))
{
conn2.Open();
SqlCommand cmdInsert = conn2.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("@id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = storeTime;
cmdInsert.Parameters.Add("@messageText", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = messageText;
cmdInsert.ExecuteNonQuery();
}
如果您使用:
Connection.ContextConnection = true;
然后它将使用与 CLR Sproc 运行 相同的连接 - 您需要打开一个 new 连接。
我正在尝试将日志写入事务内的另一个数据库,这样即使事务被回滚,日志也会继续存在。我读过 this answer 上面写着:
One possibility is to use a CLR stored procedure to do the logging. This can open its own connection to the database outside the transaction and enter and commit the log data.
所以我使用 this article:
创建了 CLR 存储过程[SqlProcedure]
public static void Voice(SqlString procedureName, SqlInt32 id)
{
Connection = new SqlConnectionStringBuilder();
Connection.ContextConnection = true;
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(Connection.ToString()))
{
conn.Open();
SqlCommand cmdInsert = conn.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("@id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = id;
cmdInsert.Parameters.Add("@procedureName", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = procedureName;
cmdInsert.ExecuteNonQuery();
}
transScope.Complete();
}
}
但是,在 SQL 服务器:
中执行并回滚存储过程后,数据未保存BEGIN TRAN
EXEC dbo.SayHelloVoice @id = 1,
@procedureName = N'FooProcedure'
ROLLBACK TRAN
我们有三个环境:
dev
。服务器名称是Q-SQL001
test
。服务器名称是Q-SQL002
prod
。服务器名称是Q-SQL003
所以这个 CLR 存储过程应该适用于所有环境。
你能说说我做错了什么吗? 任何帮助将不胜感激!
更新:
所以工作版是这样的。非常感谢 @Milney:
var serverName = string.Empty;
var dbName = string.Empty;
serverName = SqlExecuteScalar("SELECT @@SERVERNAME");
dbName = SqlExecuteScalar("SELECT DB_NAME()");
SqlConnectionStringBuilder sqlConn = new SqlConnectionStringBuilder();
sqlConn.InitialCatalog = dbName;
sqlConn.DataSource = serverName;
sqlConn.IntegratedSecurity = true;
sqlConn.ContextConnection = false;
sqlConn.Enlist = false;
sqlConn.ApplicationName = "New application";
var sql = "USE FooDatabase
INSERT INTO dbo.MyTable ..."
using (SqlConnection conn2 = new SqlConnection(sqlConn.ConnectionString))
{
conn2.Open();
SqlCommand cmdInsert = conn2.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("@id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = storeTime;
cmdInsert.Parameters.Add("@messageText", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = messageText;
cmdInsert.ExecuteNonQuery();
}
如果您使用:
Connection.ContextConnection = true;
然后它将使用与 CLR Sproc 运行 相同的连接 - 您需要打开一个 new 连接。