Having reliably set aside the isolation level for a while, let's focus on what your code does:
5 Parallel, TestContract, contractId , ?
TestContract contract id, , Number .
.
?
, , , Serializable.
SQL Server Serializable ( ):
, , . , , . , - , . . , . concurrency , . , HOLDLOCK SELECT .
, , , , TaskA TaskB contractId=123, Serializable .
, :
- TaskA
- TaskB
- TaskA
Transaction 1234 Serializable Isolation Level - TaskB
Transaction 5678 Serializable Isolation Level - TaskA
SELECT * FROM ContractRanges WHERE ContractId = 123.
. SQL Server ContractRanges , ContractId = 123, . - TaskB
SELECT, lock ContractId = 123 ContractRanges.
, , .
- TaskA
Number TaskB Number
TaskA SaveChanges, , , .
, 1234, Number , , 5678, SQL lock , , .
TaskB, SaveChanges, , TaskA, Number 123. lock , 1234 TaskA.
1234 TaskA, Transaction 5678, 5678, Transaction 1234, , , , , .
SQL Server , , victim, .
, , , Serializable, , . Serializable - , , concurrency, .
Serializable, Number .
Snapshot Isolation
:
. , , .
, , . , Snapshot concurrency.
MSDN ( , ):
, , , , , . . , , . , , .
, , SNAPSHOT . SNAPSHOT . , , SNAPSHOT .
, SNAPSHOT , , , . SNAPSHOT , . .
ALLOW_SNAPSHOT_ISOLATION ON, , SNAPSHOT . SNAPSHOT , ALLOW_SNAPSHOT_ISOLATION ON .
SNAPSHOT , ; . SNAPSHOT , , SNAPSHOT. .
, SNAPSHOT, , . , UPDATE , SELECT , .
, " ":
- ,
Number 2 123 - TaskA
- TaskB
- TaskA
Transaction 1234 - TaskB
Transaction 5678
Number = 2 123.
TaskA SELECT * FROM ContractRanges WHERE ContractId = 123. Snapshot , locks.
TaskB SELECT, locks.
- TaskA
Number 3 TaskB Number 3
TaskA, SaveChanges, , , SQL Server , , , , , , , Number 3 .
TaskB, SaveChanges . SQL Server , , . Number 2, 3. Update Exception.
, , TaskB , TaskA , TaskB.
, , , Serializable Snapshot , fix it.
, , , - , contract. , , . , , , concurrency .
, , , , Serializable, deadlocks, . , Snapshot .
, OptmisticConcurrencyException, , .
, , , , , , , , , , , , , .
, , - , OptmitisticConcurrencyException. , , , .