如何从实体框架 DbContext 收集当前的 SQL Server 会话 ID?

Posted

技术标签:

【中文标题】如何从实体框架 DbContext 收集当前的 SQL Server 会话 ID?【英文标题】:How can I collect the current SQL Server Session ID from an Entity Framework DbContext? 【发布时间】:2014-02-19 17:12:15 【问题描述】:

有没有办法确定打开的DbContext 的当前 SQL Server 会话 ID (@@SPID),而不是直接对数据库进行 SQL 查询?

如果有,是否保证 SQL Server 会话 ID 将保持不变,直到释放 DbContext 并将其连接释放回实体框架连接池?类似的东西:

using (MyEntities db = new MyEntities()) 

    // the following 3 pieces of code are not existing properties and will result in compilation errors
    // I'm just looking for something similar to the following 3 lines
    db.CurrentSessionId; //error
    db.Database.CurrentSessionId; //error
    ((IObjectContextAdapter)db).ObjectContext.Connection.CurrentSessionId; //error

    // the following code will work, but will this session id be the same until the original DbContext is disposed?
    // is there any chance that a db.Database.SqlQuery call will spin off it's own connection from the pool?
    short spid = db.Database.SqlQuery<short>("SELECT @@SPID").FirstOrDefault();

【问题讨论】:

【参考方案1】:

首先,单独的 Dbcontext 将不会打开数据库上的任何 sql 进程。查询确实

所以在这种情况下,当您运行 SELECT @@SPID 时,您肯定会打开一个具有新 ID 的新进程。

好消息是 Entityframework 将使用相同的过程来运行您的后续查询。所以理想情况下,在同一个 using 块中,您将始终获得相同的 @@SPID 值。

你可以运行这个查询

select *
from    master.dbo.sysprocesses
where program_name = 'EntityFramework' 

观察与实体框架关联的数据库上的当前进程。

然后您可以使用下面的查询来获取与特定进程关联的 SQL 语句。有关更多信息,请在此处查看接受的答案:List the queries running on SQL Server

declare
    @spid int
,   @stmt_start int
,   @stmt_end int
,   @sql_handle binary(20)

set @spid = XXX -- Fill this in

select  top 1
    @sql_handle = sql_handle
,   @stmt_start = case stmt_start when 0 then 0 else stmt_start / 2 end
,   @stmt_end = case stmt_end when -1 then -1 else stmt_end / 2 end
from    master.dbo.sysprocesses
where   spid = @spid
order by ecid

SELECT
    SUBSTRING(  text,
            COALESCE(NULLIF(@stmt_start, 0), 1),
            CASE @stmt_end
                WHEN -1
                    THEN DATALENGTH(text)
                ELSE
                    (@stmt_end - @stmt_start)
                END
        )
FROM ::fn_get_sql(@sql_handle)

【讨论】:

有趣。我仍在尝试围绕 Entity Framework 如何处理连接池。我的问题源于这样一个事实,即我将来自 webapi 请求的用户/设备信息存储在以@@spid 作为主键的表中,然后通过 EntityFramework 在另一个表上进行二次更改。目标是在该表上获得触发器以通过当前@@spid 选择用户/设备并存储有关更改的审计信息。我们发现大约 1/50,000 次,@@spid 将在这些触发器执行时存储错误的用户/设备信息。

以上是关于如何从实体框架 DbContext 收集当前的 SQL Server 会话 ID?的主要内容,如果未能解决你的问题,请参考以下文章

如何从DbContext中清除未插入的POCO? - 实体框架代码优先

如何刷新实体框架核心 DBContext?

自动从数据库生成实体模型到当前的DbContext类

实体框架:如何防止 dbcontext 被多个线程访问?

如何在服务器端 Blazor 组件中访问实体框架 DbContext 实体

我应该如何编写转换数据的实体框架迁移(最好使用 DbContext)?