@ Эд Гиннес,
(я знаю, что это старая ветка, но для тех, кому это может понадобиться в будущем)
; tldr answer: Не обошлось без некоторых изменений кода (в основном это неразрывные и разумные изменения IMHO).
Очень странно, что Microsoft не раскрывает SPID после открытия объекта подключения. Например, я вижу имя версии SQL и другие специфические свойства SQL Server, которые можно получить из объекта SqlConnection, но не из SPID.
подробности:
Каждому SQLConnection назначается один SPID. Это получается с помощью команды T-SQL @@ SPID, но выполняется на стороне SQL Server. Хитрость заключается в том, чтобы передать это вместе с основной работой, выполняемой на стороне SQL Server, и прочитать ее на стороне C #.
Четыре возможных сценария, для которых требуется SPID.
- Вы выполняете хранимую процедуру, которая возвращает набор результатов (минус спид)
- Вы делаете INS / UPD / DEL хранимой процедурой.
- Вы выполняете подготовленные SQL-сообщения на лету (встроенные) из ADO.Net (да!
- Вы вставляете данные непосредственно в таблицу с помощью SqlBulkCopy
1. Хранимая процедура, которая возвращает набор результатов
Допустим, у вас есть SP (USP_GetDBDetails), который возвращает строки из главной базы данных. Нам нужно добавить строку кода в существующий SQL Stmt, чтобы вернуть SPID и получить его на стороне C #, используя тип Paramter для получения ReturnValue. Основные Resultsets также могут быть прочитаны.
Хранимые процедуры - прекрасная вещь. Они могут одновременно возвращать возвращаемое значение И набор результатов И параметр OutPut. В этом случае на стороне SP нам нужно только добавить дополнительное возвращаемое значение в конце SP, который выполняется ADO. Сеть с использованием SqlConnection. Мы делаем это, как показано в коде 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
Теперь для захвата SPID на стороне C # (при необходимости измените строку подключения):
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 выполняет SP, который обрабатывает INS / UPS / DEL
Добавьте RETURN @@ SPID в конце SP, который отвечает за INS / UPD / DEL, так же, как мы это делали для сценария 1.
И на стороне C # для получения SPID .. все остается таким же, как в Сценарии 1, за исключением секции чтения . Удалите 4 строки в разделе Reader и замените эту строку ниже. (и, очевидно, цикл foreach для итерации DataTable dt не понадобится)
sqlcomm.ExecuteNonQuery();
3. INS / UPD / DEL с использованием встроенного SQL
Переместите эти stmts в хранимую процедуру и выполните шаги для сценария 2. Могут быть способы сделать некоторую акробатику T-SQL, чтобы внедрить @@ SPID и вернуть его, возможно, используя опцию MultipleActiveResultSets, но не очень Elegant IMO.
4. SqlBulkCopy .
Для этого потребуется запросить таблицу, чтобы получить спид. Поскольку нет хранимой процедуры для возврата SPID из SqlServer, который можно перехватить.
Нам нужно добавить дополнительный столбец типа INT для хранения значения SPID следующим образом:
ALTER TABLE dbo.TBL_NAME ADD
SPID int NOT NULL Default( @@SPID )
GO
При этом SQL Server автоматически вставит значение SPID во вновь добавленный столбец. Никакого изменения кода не потребуется на стороне C # ADO, которая обрабатывает BulkCopy. Типичный код Bulkcopy ADO выглядит следующим образом, и он должен продолжать работать после команды ALTER TABLE, указанной выше.
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
}
}
}
Таким образом, чтобы проверить вывод, выберите отдельный идентификатор SPID из dbo.TBL_NAME
Вот и все. Надеюсь, это кому-нибудь поможет.