我可以使用GetHashCode()来识别对象,但有没有办法识别SqlConnection对象获得的实际sql连接?
我(仍在)尝试调试涉及池连接和应用程序角色的问题,如果我能够可靠地识别底层的sql连接,它可以帮助很多。
以下是一些可能说明问题的代码
SqlConnection c = new SqlConnection(myConnString);
c.Open(); // GetHashCode == "X"
c.Close(); // returns connection to pool
c.Open; // GetHashCode() == "X" but possibly different pooled connection?
当我写这个问题时,我发现我可能想要的是连接的SPID。遗憾的是,由于我正在尝试解决的错误,当SQL连接被删除时,SPID不可用(所以在我最感兴趣的时候,我无法在该连接上运行命令来获取SPID)
还有其他好主意吗?
答案 0 :(得分:2)
@Ed Guiness,
(我知道这是一个旧线程,但为了将来可能需要这个的人的利益)
; tldr回答:并非没有一些代码更改(主要是非破坏和合理的更改恕我直言)。
非常奇怪的是,一旦连接对象被打开,Microsoft就不会公开SPID。我可以看到例如SQL版本名称和其他SQL Server特定属性,我可以从SqlConnection对象而不是SPID获取。
详细说明:
为每个SQLConnection分配一个SPID。这是使用T-SQL Command @@ SPID获得的,但这在SQL Server端执行。 Trick将把它与SQL Server端正在完成的主要工作一起传递,并在C#端读取它。
需要SPID的四种可能方案。
<强> 1。返回结果集的存储过程
假设您有一个从主db返回Rows的SP(USP_GetDBDetails)。我们需要向Existing SQL Stmt添加一行代码以返回SPID,并使用Paramter类型在C#Side获取它以检索ReturnValue。也可以读取主要的Resultsets。
存储过程是一件很美好的事情。 他们可以同时返回返回值和结果集以及OutPut参数。在这种情况下,在SP端我们只需要在ADO正在执行的SP末尾添加额外的返回值.Net使用SqlConnection.We执行此操作,如下面的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在负责INS / UPD / DEL的SP末尾添加RETURN @@ SPID,就像我们在场景1中所做的那样。
在C#Side获取SPID ..除了阅读器部分之外,一切都与场景1中的相同。删除“读取器”部分下的4行,并替换为下面的这一行。 (显然,不需要迭代DataTable dt的foreach循环)
sqlcomm.ExecuteNonQuery();
第3。 INS / UPD / DEL使用内联SQL
将这些stmts移动到存储过程并按照场景2的步骤操作。可能有办法做一些T-SQL杂技来注入@@ SPID并通过使用MultipleActiveResultSets选项返回它,但不是非常优雅的IMO。
<强> 4。 SqlBulkCopy的即可。
这将需要查询表以获取spid。由于没有Stored过程从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
多数民众赞成。希望能有所帮助。
答案 1 :(得分:1)
您可以在连接字符串中设置应用程序名称,然后在SQL Server中可以看到。通常它是默认的SQL客户端,但您可以覆盖:
"Integrated Security=true;Initial Catalog=Northwind;server=(local);Application Name=MyKeyword"
此属性可以通过SqlConnection实例的ConnectionString属性读回。
编辑:正如edg所指出的,连接字符串定义了哪个连接池,所以这可能不起作用。
答案 2 :(得分:0)
不是直接的答案,而是你应该注意的事情。对象的哈希码在其整个生命周期内不应更改。如果确实如此,那么你可以将一个对象放入一个哈希集合中,更改它的哈希码然后再无法从集合中检索它。
如果附加调试器并查看私有字段,是否可以将某种内部标识符转换为?如果是这样,您可以在调试期间通过反射访问它,如果必须的话。
答案 3 :(得分:0)
如果我正确理解您的问题,理查德的答案将无法帮助您,因为您正在寻找底层.NET连接池中的实际对象。我也不相信哈希会有所帮助,因为你正在查看基础池。
我本身没有答案,而是一个建议。获取Reflector(现在是RedGate产品)的副本并通过System.Data.DLL查看底层池中的内容存储方式。我不确定它会给你一个快速简单的答案,但如果有任何事情你可以反思以获得帮助调试你的问题的答案,它将会在那里。
顺便说一下,你想解决的问题是什么?答案 4 :(得分:0)
你可以尝试的一件事是
SqlConnection.ClearPool();
或
SqlConnection.ClearAllPools();
看看你是否可以隔离你面临的任何问题。
答案 5 :(得分:0)
不是说这是不可能的,但我还没有找到任何办法。