LINQ + TransactionScope will not change isolation level in SQL Server Profiler
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://c开发者_高级运维onnect.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?
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
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.
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'.
精彩评论