C# 确定SqlTransaction是写入数据还是只读

C# 确定SqlTransaction是写入数据还是只读,c#,sql-server,ado.net,C#,Sql Server,Ado.net,首先我要说,我非常确定这是不可能的。谷歌没有发现有人问这个问题,所以我抱着悲观的希望 我正在使用SqlTransaction连接到数据库,并允许多个使用者在我关闭它之前使用该事务。即使可能使用了存储过程,也可以确定事务是否仅用于读取数据或读取/写入数据?除了执行一些不神圣的差异之外,是否存在一些属性或SQL方法可以检查这一点?嗯,这只是一个想法。我在想类似于。。在数据库中创建一个表,调用CountRead和另一个表CountWrite,然后,如果查询是SELECT,则将查询修改为在read ta

首先我要说,我非常确定这是不可能的。谷歌没有发现有人问这个问题,所以我抱着悲观的希望

我正在使用SqlTransaction连接到数据库,并允许多个使用者在我关闭它之前使用该事务。即使可能使用了存储过程,也可以确定事务是否仅用于读取数据或读取/写入数据?除了执行一些不神圣的差异之外,是否存在一些属性或SQL方法可以检查这一点?

嗯,这只是一个想法。我在想类似于。。在数据库中创建一个表,调用CountRead和另一个表CountWrite,然后,如果查询是SELECT,则将查询修改为在read table中写入,如果查询是INSERT或其他内容,则将查询修改为在write table中写入。然后,当您想检查是否只读或写时,您只需要在这些表已经有数据的情况下读取它们,您可以在应用程序启动时删除或删除所有数据,或者检查开始时的计数

然后,通过对此表进行简单的选择,您将能够检查是否只使用了读取查询,或者只使用了写入查询,或者两者都使用,以及使用了多少次

正如我所说,这只是一个想法;我希望这能有所帮助,或者至少能让你对如何做有所了解。您可以这样查询:

SELECT writes FROM sys.dm_exec_sessions WHERE session_id = @@SPID
不过,这会增加一些开销。我认为DMV在运行的会话数上是打开的。系统将减慢会话的速度。最终,它变成了负标度的情况


请注意,这是每个会话的值。如果每次打开SqlConnection对象时,每个会话都有多个事务,则将累计跟踪写入。您需要对此做出解释,或者在另一个答案中使用这个想法。

您可以使用sys.dm_uu视图检查事务状态

打开事务但未完成任何工作时,仅选择“仅”,它不会注册,但如果执行任何工作,则事务日志的大小会增加

先试试这个。。。注意你的SPID

USE tempdb
begin tran
create table dave (id int)
insert into dave (id) select 1
-- rollback tran
让事务保持打开状态,然后使用以下替换spid来查看事务:

select database_transaction_log_bytes_used, *
from sys.dm_tran_database_transactions dt 
inner join sys.dm_tran_active_transactions at on (at.transaction_id = dt.transaction_id)   
inner join sys.dm_tran_session_transactions st on (st.transaction_id = dt.transaction_id) 
where (dt.database_id = DB_ID('tempdb')) and (st.is_user_transaction=1) 
and session_id=83
然后回滚原始文件

然后试试这个:

USE tempdb
begin tran
select getdate()
-- rollback tran
并在sys.dm_uu视图上运行上述操作

在事务中有记录之前,该视图为空。选择不被记录

别忘了把它全部倒回去


因此,您可以编写一个proc/视图,在关闭事务之前可以进行查询,前提是您知道spid足够容易,可以使用SELECT@@spid进行查询,该spid将返回活动会话的日志大小

我也怀疑这是否可以做到,但这是一个有趣的问题+1这是为了什么?实际上有几个。第一个是错误日志记录,另一个是性能分析。但实际上这是一个普遍的问题,如果可能的话,它会有很多用例。这个解决方案可以工作,但它依赖于所有消费者的协调。如果一些顽皮的存储过程忘记更新,那么它将错误地报告只读操作。正如我所说,这只是一个尝试帮助的想法:但是你是对的@Tyrsius你能解释这和Jiggs答案之间的区别吗?@Tyrsius我不确定这两种不同的技术是否会检测不同类型的写入,或者它们是否相同。如果它们产生相同的结果,我认为这是可能的,那么选择一个更简单、更快的结果。这可能是会话写入列。如果您使用我的初始事务场景进行测试,在将一行插入测试表后写入=0。@JiggsJedi我刚刚执行了您答案中的第一个SQL块,然后运行了我的语句。它显示了你的写作。我错过了什么吗?不确定,也许我错过了什么。。。你犯了交通罪吗?我在一个开放的传输上得到0个写入。。。很奇怪。