@埃德吉尼斯,
(我知道这是一个旧线程,但为了将来可能需要它的人的利益)
;tldr 回答:并非没有一些代码更改(主要是非破坏性和合理的更改恕我直言)。
非常奇怪的是,一旦打开连接对象,Microsoft 就不会公开 SPID。例如,我可以看到可以从 SqlConnection 对象而不是 SPID 获得的 SQL 版本名称和其他 SQL Server 特定属性。
细节:
每个 SQLConnection 都分配有一个 SPID。这是使用 T-SQL 命令@@SPID 获得的,但这在 SQL Server 端执行。诀窍是将它与在 SQL Server 端完成的主要工作一起传递,并在 C# 端读取它。
需要 SPID 的四种可能情况。
- 您正在执行一个返回结果集的存储过程(减去 spid)
- 您正在执行 INS/UPD/DEL 存储过程。
- 您正在从 ADO.Net (yikes!!) 运行 Prepared SQL stms On the fly (inline) 来执行 CRUD 操作(即没有存储过程的场景 1 和 2)
- 您正在使用 SqlBulkCopy 将数据直接插入到表中
1. 返回结果集的存储过程
假设您有一个从主数据库返回行的 SP (USP_GetDBDetails)。我们需要在 Existing SQL Stmt 中添加一行代码来返回 SPID 并在 C# 端使用 Paramter 类型获取它以检索 ReturnValue。也可以读取主要的结果集。
存储过程是一个美丽的东西。它们可以同时返回一个返回值和一个结果集和一个输出参数。在这种情况下,在 SP 端,我们只需要在 ADO.Net 使用 SqlConnection 执行的 SP 的末尾添加额外的返回值。我们这样做如下面的 T-SQL 代码所示:
CREATE Procedure [dbo].[USP_GetDBDetails]
AS
BEGIN
SELECT
database_id,
name,
create_date
FROM [sys].[databases]
Return @@SPID -- Line of Code that needs to be added to return the SPID
END
现在在 C# 端捕获 SPID(根据需要修改连接字符串):
using (SqlConnection conn = new SqlConnection(@"Data Source=(local);Initial Catalog=master;Persist Security Info=True;Integrated Security =SSPI;"))
{
string strSql = "USP_GetDBDetails";
SqlCommand sqlcomm = new SqlCommand();
sqlcomm.CommandText = strSql;
sqlcomm.CommandType = CommandType.StoredProcedure;
sqlcomm.Connection = conn;
SqlParameter returnValueParam = sqlcomm.Parameters.Add("@ReturnValue", SqlDbType.Int);
returnValueParam.Direction = ParameterDirection.ReturnValue;
conn.Open();
**// Reader Section**
SqlDataReader rdr = sqlcomm.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rdr); // Get the Reultset into a DataTable so we can use it !
rdr.Close(); // Important to close the reader object before reading the return value.
// Lets get the return value which in this case will be the SPID for this connection.
string spid_str = returnValueParam.Value.ToString();
int spid = (int)sqlcomm.Parameters["@ReturnValue"].Value; // Another Way to get the return value.
Console.WriteLine("SPID For this Conn = {0} ", spid);
// To use the Reult Sets that was returned by the SP:
foreach (DataRow dr in dt.Rows)
{
string dbName = dr["Name"].ToString();
// Code to use the Other Columns goes here
}
}
输出 :
SPID For this Conn = 66
2.如果Connection对象正在执行一个处理INS/UPS/DEL的SP
就像我们在场景 1 中所做的那样,在负责 INS/UPD/DEL 的 SP 的末尾添加 RETURN @@SPID。
在 C# 端获取 SPID .. 一切都与场景 1 中的相同,除了阅读器部分。删除 Reader Section 下的 4 行,并用下面的这一行替换。(显然,迭代 DataTable dt 的 foreach 循环不是必需的)
sqlcomm.ExecuteNonQuery();
3. INS/UPD/DEL 使用内联 SQL
将这些 stmts 移动到存储过程中并按照场景 2 的步骤进行操作。可能有一些方法可以做一些 T-SQL 杂技来注入 @@SPID 并通过可能使用 MultipleActiveResultSets 选项返回它,但不是很优雅的 IMO。
4. SqlBulkCopy。
这将需要查询表以获取 spid。由于没有存储过程可以从 SqlServer 返回可以捕获的 SPID。
我们需要添加一个额外的 INT 类型列来保存 SPID 值,如下所示:
ALTER TABLE dbo.TBL_NAME ADD
SPID int NOT NULL Default( @@SPID )
GO
通过这样做,SQL Server 将自动将 SPID 值插入到新添加的列中。在处理 BulkCopy 的 C# ADO 端不需要更改代码。典型的 Bulkcopy ADO 代码如下所示,它应该在上面的 ALTER TABLE Stmt 之后继续工作。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
DataTable dt = new DataTable();
dt.Columns.Add("Col1");
dt.Columns.Add("Col2");
string[] row = { "Col1Value", "Col2Value" };
dt.Rows.Add(row);
bulkCopy.DestinationTableName = "TBL_NAME_GOES_HERE"; //TBL_NAME
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(dt);
}
catch (SqlException ex)
{
// Handle Exception
}
}
}
因此,要检查输出,请从 dbo.TBL_NAME 中选择不同的 SPID
就是这样 。希望对某人有所帮助。