|
1 | 1 | using System.Linq;
|
2 |
| -using NHibernate.AdoNet; |
3 |
| -using NHibernate.Cfg; |
4 |
| -using NHibernate.Engine; |
| 2 | +using System.Transactions; |
| 3 | +using NHibernate.Dialect; |
| 4 | +using NHibernate.DomainModel.Northwind.Entities; |
| 5 | +using NHibernate.Exceptions; |
5 | 6 | using NHibernate.Linq;
|
6 | 7 | using NUnit.Framework;
|
7 | 8 |
|
| 9 | + |
8 | 10 | namespace NHibernate.Test.Linq
|
9 | 11 | {
|
10 | 12 | public class QueryLock : LinqTestCase
|
11 | 13 | {
|
12 |
| - |
13 | 14 | [Test]
|
14 | 15 | public void CanSetLockLinqQueries()
|
15 | 16 | {
|
16 |
| - var result = (from e in db.Customers |
17 |
| - where e.CompanyName == "Corp" |
18 |
| - select e).SetLockMode(LockMode.Upgrade).ToList(); |
| 17 | + using (session.BeginTransaction()) |
| 18 | + { |
| 19 | + var result = (from e in db.Customers |
| 20 | + select e).SetLockMode(LockMode.Upgrade).ToList(); |
19 | 21 |
|
| 22 | + Assert.That(result, Has.Count.EqualTo(91)); |
| 23 | + Assert.That(session.GetCurrentLockMode(result[0]), Is.EqualTo(LockMode.Upgrade)); |
| 24 | + AssertSeparateTransactionIsLockedOut(result[0].CustomerId); |
| 25 | + } |
20 | 26 | }
|
21 | 27 |
|
22 | 28 |
|
23 | 29 | [Test]
|
24 | 30 | public void CanSetLockOnLinqPagingQuery()
|
25 | 31 | {
|
26 |
| - var result = (from e in db.Customers |
27 |
| - where e.CompanyName == "Corp" |
28 |
| - select e).Skip(5).Take(5).SetLockMode(LockMode.Upgrade).ToList(); |
29 |
| - } |
| 32 | + using (session.BeginTransaction()) |
| 33 | + { |
| 34 | + var result = (from e in db.Customers |
| 35 | + select e).Skip(5).Take(5).SetLockMode(LockMode.Upgrade).ToList(); |
30 | 36 |
|
| 37 | + Assert.That(result, Has.Count.EqualTo(5)); |
| 38 | + Assert.That(session.GetCurrentLockMode(result[0]), Is.EqualTo(LockMode.Upgrade)); |
| 39 | + AssertSeparateTransactionIsLockedOut(result[0].CustomerId); |
| 40 | + } |
| 41 | + } |
31 | 42 |
|
32 | 43 | [Test]
|
33 | 44 | public void CanLockBeforeSkipOnLinqOrderedPageQuery()
|
34 | 45 | {
|
35 |
| - var result = (from e in db.Customers |
36 |
| - orderby e.CompanyName |
37 |
| - select e) |
38 |
| - .SetLockMode(LockMode.Upgrade).Skip(5).Take(5).ToList(); |
| 46 | + using (session.BeginTransaction()) |
| 47 | + { |
| 48 | + var result = (from e in db.Customers |
| 49 | + orderby e.CompanyName |
| 50 | + select e) |
| 51 | + .SetLockMode(LockMode.Upgrade).Skip(5).Take(5).ToList(); |
39 | 52 |
|
| 53 | + Assert.That(result, Has.Count.EqualTo(5)); |
| 54 | + Assert.That(session.GetCurrentLockMode(result[0]), Is.EqualTo(LockMode.Upgrade)); |
| 55 | + AssertSeparateTransactionIsLockedOut(result[0].CustomerId); |
| 56 | + } |
| 57 | + } |
40 | 58 |
|
| 59 | + private void AssertSeparateTransactionIsLockedOut(string customerId) |
| 60 | + { |
| 61 | + using (new TransactionScope(TransactionScopeOption.Suppress)) |
| 62 | + using (var s2 = OpenSession()) |
| 63 | + using (s2.BeginTransaction()) |
| 64 | + { |
| 65 | + // TODO: We should try to verify that the exception actually IS a locking failure and not something unrelated. |
| 66 | + Assert.Throws<GenericADOException>( |
| 67 | + () => |
| 68 | + { |
| 69 | + var result2 = ( |
| 70 | + from e in s2.Query<Customer>() |
| 71 | + where e.CustomerId == customerId |
| 72 | + select e |
| 73 | + ).SetLockMode(LockMode.UpgradeNoWait) |
| 74 | + .WithOptions(o => o.SetTimeout(5)) |
| 75 | + .ToList(); |
| 76 | + Assert.That(result2, Is.Not.Null); |
| 77 | + }, |
| 78 | + "Expected an exception to indicate locking failure due to already locked."); |
| 79 | + } |
41 | 80 | }
|
42 | 81 |
|
| 82 | + [Test] |
| 83 | + [Description("Verify that different lock modes are respected even if the query is otherwise exactly the same.")] |
| 84 | + public void CanChangeLockModeForQuery() |
| 85 | + { |
| 86 | + // Limit to a few dialects where we know the "nowait" keyword is used to make life easier. |
| 87 | + Assume.That(Dialect is MsSql2000Dialect || Dialect is Oracle8iDialect || Dialect is PostgreSQL81Dialect); |
| 88 | + |
| 89 | + using (session.BeginTransaction()) |
| 90 | + { |
| 91 | + var result = BuildQueryableAllCustomers(db.Customers, LockMode.Upgrade).ToList(); |
| 92 | + Assert.That(result, Has.Count.EqualTo(91)); |
43 | 93 |
|
44 |
| - } |
| 94 | + using (var logSpy = new SqlLogSpy()) |
| 95 | + { |
| 96 | + // Only difference in query is the lockmode - make sure it gets picked up. |
| 97 | + var result2 = BuildQueryableAllCustomers(session.Query<Customer>(), LockMode.UpgradeNoWait) |
| 98 | + .ToList(); |
| 99 | + Assert.That(result2, Has.Count.EqualTo(91)); |
| 100 | + |
| 101 | + Assert.That(logSpy.GetWholeLog().ToLower(), Does.Contain("nowait")); |
| 102 | + } |
| 103 | + } |
| 104 | + } |
45 | 105 |
|
| 106 | + private static IQueryable<Customer> BuildQueryableAllCustomers( |
| 107 | + IQueryable<Customer> dbCustomers, |
| 108 | + LockMode lockMode) |
| 109 | + { |
| 110 | + return (from e in dbCustomers select e).SetLockMode(lockMode).WithOptions(o => o.SetTimeout(5)); |
| 111 | + } |
| 112 | + } |
46 | 113 | }
|
47 | 114 |
|
| 115 | + |
0 commit comments