LINQ + TransactionScope will not change isolation level in SQL Server Profiler

笑着哭i 提交于 2020-01-03 16:51:18

问题


I'm using the following format for commiting changes to my db using linq.

Begin Transaction (Scope Serialized, Required)
    Check Business Rule 1...N
    MyDataContext.SubmitChanges()
    Save Changes Done In Previous Query To Log File
End Transaction Scope

But in the SQL Server profiler I see the following line in the Connection:Start.

set transaction isolation level read committed

I went through this (http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/93a45026-0425-4d49-a4ac-1b882e90e6d5) and thought I had an answer;

Until I saw this (https://connect.microsoft.com/VisualStudio/feedback/details/565441/transactionscope-linq-to-sql?wa=wsignin1.0) on Microsoft Connect.

Can someone please tell me whether my code is actually executed under Serialized Isolation Level or whether it is infact just running under read committed?


回答1:


It depends on how you created the transaction.

If you executed inline SQL to begin it (EG. BEGIN TRAN), L2S will not be aware of the transaction and will spin up a new nested one in READ COMMITTED.

However, if you used System.Transaction, or have a transaction set on your DataContext, SubmitChanges will participate in that transaction.

You can see these transaction starting and stopping in Profiler if you choose the TM: Begin Tran and TM: Commit Tran event classes.

Note: ADO.Net does not issue BEGIN TRAN nor does it issue SET TRANSACTION ISOLATION in batches, this is done at a lower level.

If you really want to confirm the behavior, create a trigger on a table that inserts the current isolation level into a logging table and check on it.

You can pick up your current isolation level by running:

SELECT CASE transaction_isolation_level 
WHEN 0 THEN 'Unspecified' 
WHEN 1 THEN 'Read Uncommitted' 
WHEN 2 THEN 'Read Committed' 
WHEN 3 THEN 'Repeatable Read' 
WHEN 4 THEN 'Serializable' 
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 
FROM sys.dm_exec_sessions 
where session_id = @@SPID



回答2:


My guess is you created the DataContext, then used the TransactionScope. You have to open the connection inside the TransactionScope in order for it to enlist.




回答3:


From http://entityframework.codeplex.com/workitem/1712

TransactionScope uses remote API calls rather than SQL commands to perform transactions in SQL Server. Those API calls are not included in the a standard trace in SQL Profiler.

You can include them by going to the "Event Selection" page, clicking on the "Show all events" checkbox and the selecting all the events from the Transactions category. This will allow you to see when such events as 'TM: Begin Tran Starting', 'SQLTransaction' and 'TM: Begin Tran Completed' actually occur.

You can also check the TransactionID column for the TSQL events in the "Event Selection" page to see the to which transaction each SQL batch being executed is associated.

Unfortunately I don't know of a direct way to observe the effective isolation level under which each command is being executed in SQL Profiler. But there is an indirect way...

When a connection is opened you will see an 'Audit Login' event in the trace. In many cases this event will contain the isolation level. Now, the 'Audit Login' happens before the actual isolation level is set, so the reported isolation level won't accurately reflect the isolation level of the transaction that is about to start. Here are some tips on how to interpret it: When a connection opening actually hits a new connection it will always report the default transaction isolation level, e.g. you will see 'set transaction isolation level read uncommitted' (as I said, this is unrelated to the effective isolation level of your transaction as that one will be set at a later point) After a connection has been opened and then returned to the connection pool (i.e. closed), subsequent connection openings will actually reuse that existing connection from the pool. In this case the 'Audit Login' will report the isolation level that was set when the connection got returned to the pool the last time. This can help you see the isolation level that was used, after the fact. E.g. in your code snippet, the connection is open for a last time to roll back the transaction (because you have not marked the transaction as completed explicitly). In that 'Audit Login' event you should be able to see the isolation level that was effective when the connection was previously used to execute the query, represented by the line 'set transaction isolation level read uncommitted'.



来源:https://stackoverflow.com/questions/3911285/linq-transactionscope-will-not-change-isolation-level-in-sql-server-profiler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!