Skip to content

Commit e1ff88d

Browse files
oskarbhazzik
authored andcommitted
Strengthen asserts to verify actual locking has taken place
- Add test case to verify that a change in lock mode will avoid reusing cached query.
1 parent 9c73f04 commit e1ff88d

File tree

1 file changed

+84
-16
lines changed

1 file changed

+84
-16
lines changed

src/NHibernate.Test/Linq/QueryLock.cs

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,115 @@
11
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;
56
using NHibernate.Linq;
67
using NUnit.Framework;
78

9+
810
namespace NHibernate.Test.Linq
911
{
1012
public class QueryLock : LinqTestCase
1113
{
12-
1314
[Test]
1415
public void CanSetLockLinqQueries()
1516
{
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();
1921

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+
}
2026
}
2127

2228

2329
[Test]
2430
public void CanSetLockOnLinqPagingQuery()
2531
{
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();
3036

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+
}
3142

3243
[Test]
3344
public void CanLockBeforeSkipOnLinqOrderedPageQuery()
3445
{
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();
3952

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+
}
4058

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+
}
4180
}
4281

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));
4393

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+
}
45105

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+
}
46113
}
47114

115+

0 commit comments

Comments
 (0)