Skip to content

Commit 75b98a0

Browse files
Merge 5.3.12 into master
2 parents 6999436 + 457d767 commit 75b98a0

File tree

21 files changed

+472
-89
lines changed

21 files changed

+472
-89
lines changed

releasenotes.txt

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1-
Build 5.3.11
1+
Build 5.3.12
2+
=============================
3+
4+
Release notes - NHibernate - Version 5.3.12
5+
6+
5 issues were resolved in this release.
7+
8+
** Bug
9+
10+
* #3046 Regression for filters on entity joins with many-to-one disabled
11+
* #3029 InvalidOperationException on proxies with explicit implementation of a generic method
12+
13+
** Improvement
14+
15+
* #3043 Improve exception for query on delayed id
16+
17+
** Test
18+
19+
* #3035 Support tests in VS 2022
20+
21+
** Task
22+
23+
* #3044 Release 5.3.12
24+
25+
Build 5.3.11
226
=============================
327

428
Release notes - NHibernate - Version 5.3.11

src/NHibernate.Test.VisualBasic/Program.vb

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ Public Class Program
44
Return New NUnitLite.AutoRun(GetType(Program).Assembly).Execute(args)
55
End Function
66
End Class
7-
#End If
7+
#End If

src/NHibernate.Test/Async/Generatedkeys/Identity/IdentityGeneratedKeysTest.cs

+228-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
//------------------------------------------------------------------------------
99

1010

11+
using System.Linq;
1112
using NHibernate.Cfg;
13+
using NHibernate.Exceptions;
1214
using NUnit.Framework;
1315

1416
namespace NHibernate.Test.Generatedkeys.Identity
@@ -38,17 +40,238 @@ protected override void Configure(Configuration configuration)
3840
configuration.SetProperty(Environment.GenerateStatistics, "true");
3941
}
4042

43+
protected override void OnTearDown()
44+
{
45+
using (var s = OpenSession())
46+
using (var t = s.BeginTransaction())
47+
{
48+
s.CreateQuery("delete from MyChild").ExecuteUpdate();
49+
s.CreateQuery("delete from MySibling").ExecuteUpdate();
50+
s.CreateQuery("delete from System.Object").ExecuteUpdate();
51+
t.Commit();
52+
s.Close();
53+
}
54+
}
55+
4156
[Test]
4257
public async Task IdentityColumnGeneratedIdsAsync()
4358
{
4459
using (var s = OpenSession())
4560
using (var t = s.BeginTransaction())
4661
{
47-
MyEntity myEntity = new MyEntity("test");
48-
long id = (long) await (s.SaveAsync(myEntity));
49-
Assert.IsNotNull(id, "identity column did not force immediate insert");
50-
Assert.AreEqual(id, myEntity.Id);
51-
await (s.DeleteAsync(myEntity));
62+
var entity1 = new MyEntity("test");
63+
var id1 = (long) await (s.SaveAsync(entity1));
64+
var entity2 = new MyEntity("test2");
65+
var id2 = (long) await (s.SaveAsync(entity2));
66+
// As 0 may be a valid identity value, we check for returned ids being not the same when saving two entities.
67+
Assert.That(id1, Is.Not.EqualTo(id2), "identity column did not force immediate insert");
68+
Assert.That(id1, Is.EqualTo(entity1.Id));
69+
Assert.That(id2, Is.EqualTo(entity2.Id));
70+
await (t.CommitAsync());
71+
s.Close();
72+
}
73+
}
74+
75+
[Test]
76+
public async Task PersistOutsideTransactionAsync()
77+
{
78+
var myEntity1 = new MyEntity("test-save");
79+
var myEntity2 = new MyEntity("test-persist");
80+
using (var s = OpenSession())
81+
{
82+
// first test save() which should force an immediate insert...
83+
var initialInsertCount = Sfi.Statistics.EntityInsertCount;
84+
var id = (long) await (s.SaveAsync(myEntity1));
85+
Assert.That(
86+
Sfi.Statistics.EntityInsertCount,
87+
Is.GreaterThan(initialInsertCount),
88+
"identity column did not force immediate insert");
89+
Assert.That(id, Is.EqualTo(myEntity1.Id));
90+
91+
// next test persist() which should cause a delayed insert...
92+
initialInsertCount = Sfi.Statistics.EntityInsertCount;
93+
await (s.PersistAsync(myEntity2));
94+
Assert.AreEqual(
95+
initialInsertCount,
96+
Sfi.Statistics.EntityInsertCount,
97+
"persist on identity column not delayed");
98+
Assert.AreEqual(0, myEntity2.Id);
99+
100+
// an explicit flush should cause execution of the delayed insertion
101+
await (s.FlushAsync());
102+
Assert.AreEqual(
103+
initialInsertCount + 1,
104+
Sfi.Statistics.EntityInsertCount,
105+
"delayed persist insert not executed on flush");
106+
s.Close();
107+
}
108+
109+
using (var s = OpenSession())
110+
using (var t = s.BeginTransaction())
111+
{
112+
await (s.DeleteAsync(myEntity1));
113+
await (s.DeleteAsync(myEntity2));
114+
await (t.CommitAsync());
115+
s.Close();
116+
}
117+
}
118+
119+
[Test]
120+
public async Task PersistOutsideTransactionCascadedToNonInverseCollectionAsync()
121+
{
122+
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
123+
using (var s = OpenSession())
124+
{
125+
MyEntity myEntity = new MyEntity("test-persist");
126+
myEntity.NonInverseChildren.Add(new MyChild("test-child-persist-non-inverse"));
127+
await (s.PersistAsync(myEntity));
128+
Assert.AreEqual(
129+
initialInsertCount,
130+
Sfi.Statistics.EntityInsertCount,
131+
"persist on identity column not delayed");
132+
Assert.AreEqual(0, myEntity.Id);
133+
await (s.FlushAsync());
134+
Assert.AreEqual(
135+
initialInsertCount + 2,
136+
Sfi.Statistics.EntityInsertCount,
137+
"delayed persist insert not executed on flush");
138+
s.Close();
139+
}
140+
141+
using (var s = OpenSession())
142+
using (var t = s.BeginTransaction())
143+
{
144+
await (s.DeleteAsync("from MyChild"));
145+
await (s.DeleteAsync("from MyEntity"));
146+
await (t.CommitAsync());
147+
s.Close();
148+
}
149+
}
150+
151+
[Test]
152+
public async Task PersistOutsideTransactionCascadedToInverseCollectionAsync()
153+
{
154+
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
155+
using (var s = OpenSession())
156+
{
157+
MyEntity myEntity2 = new MyEntity("test-persist-2");
158+
MyChild child = new MyChild("test-child-persist-inverse");
159+
myEntity2.InverseChildren.Add(child);
160+
child.InverseParent = myEntity2;
161+
await (s.PersistAsync(myEntity2));
162+
Assert.AreEqual(
163+
initialInsertCount,
164+
Sfi.Statistics.EntityInsertCount,
165+
"persist on identity column not delayed");
166+
Assert.AreEqual(0, myEntity2.Id);
167+
await (s.FlushAsync());
168+
Assert.AreEqual(
169+
initialInsertCount + 2,
170+
Sfi.Statistics.EntityInsertCount,
171+
"delayed persist insert not executed on flush");
172+
s.Close();
173+
}
174+
175+
using (var s = OpenSession())
176+
using (var t = s.BeginTransaction())
177+
{
178+
await (s.DeleteAsync("from MyChild"));
179+
await (s.DeleteAsync("from MyEntity"));
180+
await (t.CommitAsync());
181+
s.Close();
182+
}
183+
}
184+
185+
[Test]
186+
public async Task PersistOutsideTransactionCascadedToManyToOneAsync()
187+
{
188+
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
189+
using (var s = OpenSession())
190+
{
191+
MyEntity myEntity = new MyEntity("test-persist");
192+
myEntity.Sibling = new MySibling("test-persist-sibling-out");
193+
await (s.PersistAsync(myEntity));
194+
Assert.AreEqual(
195+
initialInsertCount,
196+
Sfi.Statistics.EntityInsertCount,
197+
"persist on identity column not delayed");
198+
Assert.AreEqual(0, myEntity.Id);
199+
await (s.FlushAsync());
200+
Assert.AreEqual(
201+
initialInsertCount + 2,
202+
Sfi.Statistics.EntityInsertCount,
203+
"delayed persist insert not executed on flush");
204+
s.Close();
205+
}
206+
207+
using (var s = OpenSession())
208+
using (var t = s.BeginTransaction())
209+
{
210+
await (s.DeleteAsync("from MyEntity"));
211+
await (s.DeleteAsync("from MySibling"));
212+
await (t.CommitAsync());
213+
s.Close();
214+
}
215+
}
216+
217+
[Test]
218+
public async Task PersistOutsideTransactionCascadedFromManyToOneAsync()
219+
{
220+
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
221+
using (var s = OpenSession())
222+
{
223+
MyEntity myEntity2 = new MyEntity("test-persist-2");
224+
MySibling sibling = new MySibling("test-persist-sibling-in");
225+
sibling.Entity = myEntity2;
226+
await (s.PersistAsync(sibling));
227+
Assert.AreEqual(
228+
initialInsertCount,
229+
Sfi.Statistics.EntityInsertCount,
230+
"persist on identity column not delayed");
231+
Assert.AreEqual(0, myEntity2.Id);
232+
await (s.FlushAsync());
233+
Assert.AreEqual(
234+
initialInsertCount + 2,
235+
Sfi.Statistics.EntityInsertCount,
236+
"delayed persist insert not executed on flush");
237+
s.Close();
238+
}
239+
240+
using (var s = OpenSession())
241+
using (var t = s.BeginTransaction())
242+
{
243+
await (s.DeleteAsync("from MySibling"));
244+
await (s.DeleteAsync("from MyEntity"));
245+
await (t.CommitAsync());
246+
s.Close();
247+
}
248+
}
249+
250+
[Test]
251+
public async Task QueryOnPersistedEntityAsync([Values(FlushMode.Auto, FlushMode.Commit)] FlushMode flushMode)
252+
{
253+
var myEntity = new MyEntity("test-persist");
254+
using (var s = OpenSession())
255+
using (var t = s.BeginTransaction())
256+
{
257+
s.FlushMode = flushMode;
258+
259+
var initialInsertCount = Sfi.Statistics.EntityInsertCount;
260+
await (s.PersistAsync(myEntity));
261+
Assert.That(Sfi.Statistics.EntityInsertCount, Is.EqualTo(initialInsertCount),
262+
"persist on identity column not delayed");
263+
Assert.That(myEntity.Id, Is.Zero);
264+
265+
var query = s.Query<MyChild>().Where(c => c.InverseParent == myEntity);
266+
switch (flushMode)
267+
{
268+
case FlushMode.Auto:
269+
Assert.That(query.ToList, Throws.Nothing);
270+
break;
271+
case FlushMode.Commit:
272+
Assert.That(query.ToList, Throws.Exception.TypeOf(typeof(UnresolvableObjectException)));
273+
break;
274+
}
52275
await (t.CommitAsync());
53276
s.Close();
54277
}

src/NHibernate.Test/Async/NHSpecificTest/GH2549/Fixture.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
namespace NHibernate.Test.NHSpecificTest.GH2549
1616
{
1717
using System.Threading.Tasks;
18+
// Test GH3046 too, when useManyToOne is <c>true</c>.
1819
[TestFixture]
1920
public class FixtureAsync : BugTestCase
2021
{
@@ -41,16 +42,16 @@ protected override void OnTearDown()
4142
}
4243
}
4344

44-
[Test]
45-
public async Task EntityJoinFilterLinqAsync()
45+
[Theory]
46+
public async Task EntityJoinFilterLinqAsync(bool useManyToOne)
4647
{
4748
using (var s = OpenSession())
4849
{
4950
var list = await ((from p in s.Query<Person>()
5051
join c in s.Query<Customer>() on p.Name equals c.Name
5152
select p).ToListAsync());
5253

53-
s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
54+
s.EnableFilter(useManyToOne ? "DeletedCustomer" : "DeletedCustomerNoManyToOne").SetParameter("deleted", false);
5455

5556
var filteredList = await ((from p in s.Query<Person>()
5657
join c in s.Query<Customer>() on p.Name equals c.Name
@@ -61,16 +62,16 @@ join c in s.Query<Customer>() on p.Name equals c.Name
6162
}
6263
}
6364

64-
[Test]
65-
public async Task EntityJoinFilterQueryOverAsync()
65+
[Theory]
66+
public async Task EntityJoinFilterQueryOverAsync(bool useManyToOne)
6667
{
6768
using (var s = OpenSession())
6869
{
6970
Customer c = null;
7071
Person p = null;
7172
var list = await (s.QueryOver(() => p).JoinEntityAlias(() => c, () => c.Name == p.Name).ListAsync());
7273

73-
s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
74+
s.EnableFilter(useManyToOne ? "DeletedCustomer" : "DeletedCustomerNoManyToOne").SetParameter("deleted", false);
7475

7576
var filteredList = await (s.QueryOver(() => p).JoinEntityAlias(() => c, () => c.Name == p.Name).ListAsync());
7677

src/NHibernate.Test/Async/StaticProxyTest/InterfaceHandling/Fixture.cs

+16
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ protected override HbmMapping GetMappings()
9898
rc.Property(x => x.Name);
9999
});
100100

101+
mapper.Class<EntityWithExplicitGenericInterface>(
102+
rc =>
103+
{
104+
rc.Table("explGenInterface");
105+
rc.Id(x => x.Id);
106+
});
107+
101108
return mapper.CompileMappingForAllExplicitlyAddedEntities();
102109
}
103110

@@ -177,6 +184,15 @@ public async Task ProxyInterfaceIdAccessFromDifferentInterfacesAsync()
177184
}
178185
}
179186

187+
[Test]
188+
public void ProxyExplicitGenericInterfaceAsync()
189+
{
190+
using (var session = OpenSession())
191+
{
192+
Assert.That(() => session.LoadAsync<EntityWithExplicitGenericInterface>(_id), Throws.Nothing, "Failed to load EntityWithExplicitGenericInterface proxy");
193+
}
194+
}
195+
180196
private void ThrowOnIEntityNameAccess(IEntity entity)
181197
{
182198
Assert.That(() => entity.Name, Throws.TypeOf<ObjectNotFoundException>(), "IEntity.Name access should lead to proxy initialization");

0 commit comments

Comments
 (0)