Skip to content

Commit ffd4429

Browse files
authored
Merge branch 'master' into bug-2552
2 parents 57a5ed2 + a58c98d commit ffd4429

34 files changed

+1175
-137
lines changed

releasenotes.txt

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,41 @@
1-
Build 5.3.3
1+
Build 5.3.5
2+
=============================
3+
4+
Release notes - NHibernate - Version 5.3.5
5+
6+
2 issues were resolved in this release.
7+
8+
** Bug
9+
10+
* #2599 WrongClassException in Linq query
11+
12+
** Task
13+
14+
* #2606 Release 5.3.5
15+
16+
Build 5.3.4
17+
=============================
18+
19+
Release notes - NHibernate - Version 5.3.4
20+
21+
6 issues were resolved in this release.
22+
23+
** Bug
24+
25+
* #2580 InvalidWithClauseException when join polymorphic entity
26+
* #2559 Regression in caching linq query with ThenFetchMany statement.
27+
* #2549 ApplyFilter does not work on join statements in LINQ
28+
* #2537 Unable to cast "System.Linq.Expressions.UnaryExpression" to "System.Linq.Expressions.LambdaExpression".
29+
30+
** Task
31+
32+
* #2578 Add missing possible breaking changes for #2365
33+
* #2587 Release 5.3.4
34+
35+
As part of releasing 5.3.4, one missing 5.3.0 possible breaking change has been added, about
36+
custom method generators for Linq. See 5.3.0 possible breaking changes.
37+
38+
Build 5.3.3
239
=============================
340

441
Release notes - NHibernate - Version 5.3.3
@@ -135,6 +172,8 @@ Release notes - NHibernate - Version 5.3.0
135172
already exists in the set will now return false.
136173
* Calling `ISet<>.Add` or `ICollection<>.Add` on an uninitialized set mapped as `lazy="true"` with a
137174
transient element that does not override `Equals` method will not initialize the collection.
175+
* Linq custom generators deriving from `BaseHqlGeneratorForMethod` should override the
176+
`TryGetCollectionParameter` method if they have to support parameter lists.
138177

139178
** Bug
140179

src/NHibernate.Test/Async/Hql/Ast/BulkManipulation.cs

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ public async Task InsertAcrossMappedJoinFailsAsync()
223223
await (data.CleanupAsync());
224224
}
225225

226-
public async Task InsertWithGeneratedIdAsync(CancellationToken cancellationToken = default(CancellationToken))
226+
[Test]
227+
public async Task InsertWithGeneratedIdAsync()
227228
{
228229
// Make sure the env supports bulk inserts with generated ids...
229230
IEntityPersister persister = Sfi.GetEntityPersister(typeof (PettingZoo).FullName);
@@ -238,30 +239,30 @@ public async Task InsertAcrossMappedJoinFailsAsync()
238239

239240
ISession s = OpenSession();
240241
ITransaction t = s.BeginTransaction();
241-
await (s.SaveAsync(zoo, cancellationToken));
242-
await (t.CommitAsync(cancellationToken));
242+
await (s.SaveAsync(zoo));
243+
await (t.CommitAsync());
243244
s.Close();
244245

245246
s = OpenSession();
246247
t = s.BeginTransaction();
247-
int count = await (s.CreateQuery("insert into PettingZoo (name) select name from Zoo").ExecuteUpdateAsync(cancellationToken));
248-
await (t.CommitAsync(cancellationToken));
248+
int count = await (s.CreateQuery("insert into PettingZoo (name) select name from Zoo").ExecuteUpdateAsync());
249+
await (t.CommitAsync());
249250
s.Close();
250251
Assert.That(count, Is.EqualTo(1), "unexpected insertion count");
251252

252253
s = OpenSession();
253254
t = s.BeginTransaction();
254-
var pz = (PettingZoo) await (s.CreateQuery("from PettingZoo").UniqueResultAsync(cancellationToken));
255-
await (t.CommitAsync(cancellationToken));
255+
var pz = (PettingZoo) await (s.CreateQuery("from PettingZoo").UniqueResultAsync());
256+
await (t.CommitAsync());
256257
s.Close();
257258

258259
Assert.That(zoo.Name, Is.EqualTo(pz.Name));
259260
Assert.That(zoo.Id != pz.Id);
260261

261262
s = OpenSession();
262263
t = s.BeginTransaction();
263-
await (s.CreateQuery("delete Zoo").ExecuteUpdateAsync(cancellationToken));
264-
await (t.CommitAsync(cancellationToken));
264+
await (s.CreateQuery("delete Zoo").ExecuteUpdateAsync());
265+
await (t.CommitAsync());
265266
s.Close();
266267
}
267268

@@ -826,6 +827,31 @@ public async Task UpdateSetNullOnJoinedSubclassAsync()
826827
await (data.CleanupAsync());
827828
}
828829

830+
[Test]
831+
public async Task UpdateMultitableWithWhereExistsSubqueryAsync()
832+
{
833+
if (!Dialect.SupportsTemporaryTables)
834+
Assert.Ignore("Cannot perform multi-table updates using dialect not supporting temp tables.");
835+
836+
if(!Dialect.SupportsScalarSubSelects)
837+
Assert.Ignore("Dialect does not support scalar sub-select");
838+
839+
using (var s = OpenSession())
840+
using (var t = s.BeginTransaction())
841+
{
842+
String updateQryString = "update Human h " +
843+
"set h.description = 'updated' " +
844+
"where exists (" +
845+
" select f.id " +
846+
" from h.friends f " +
847+
" where f.name.last = 'Public' " +
848+
")";
849+
await (s.CreateQuery(updateQryString).ExecuteUpdateAsync());
850+
851+
await (t.CommitAsync());
852+
}
853+
}
854+
829855
#endregion
830856

831857
#region DELETES
@@ -834,25 +860,7 @@ public async Task UpdateSetNullOnJoinedSubclassAsync()
834860
public async Task DeleteWithSubqueryAsync()
835861
{
836862
// setup the test data...
837-
using (var s = OpenSession())
838-
using (var t = s.BeginTransaction())
839-
{
840-
var owner = new SimpleEntityWithAssociation { Name = "myEntity-1" };
841-
owner.AddAssociation("assoc-1");
842-
owner.AddAssociation("assoc-2");
843-
owner.AddAssociation("assoc-3");
844-
await (s.SaveAsync(owner));
845-
var owner2 = new SimpleEntityWithAssociation { Name = "myEntity-2" };
846-
owner2.AddAssociation("assoc-1");
847-
owner2.AddAssociation("assoc-2");
848-
owner2.AddAssociation("assoc-3");
849-
owner2.AddAssociation("assoc-4");
850-
await (s.SaveAsync(owner2));
851-
var owner3 = new SimpleEntityWithAssociation { Name = "myEntity-3" };
852-
await (s.SaveAsync(owner3));
853-
await (t.CommitAsync());
854-
s.Close();
855-
}
863+
await (CreateSimpleEntityWithAssociationDataAsync());
856864

857865
// now try the bulk delete
858866
using (var s = OpenSession())
@@ -868,14 +876,7 @@ public async Task DeleteWithSubqueryAsync()
868876
}
869877

870878
// finally, clean up
871-
using (var s = OpenSession())
872-
using (var t = s.BeginTransaction())
873-
{
874-
await (s.CreateQuery("delete SimpleAssociatedEntity").ExecuteUpdateAsync());
875-
await (s.CreateQuery("delete SimpleEntityWithAssociation").ExecuteUpdateAsync());
876-
await (t.CommitAsync());
877-
s.Close();
878-
}
879+
await (CleanSimpleEntityWithAssociationDataAsync());
879880
}
880881

881882
[Test]
@@ -1079,6 +1080,56 @@ public async Task DeleteSyntaxWithCompositeIdAsync()
10791080
s.Close();
10801081
}
10811082

1083+
[Test]
1084+
public async Task DeleteSubQueryReferencingTargetPropertAsync()
1085+
{
1086+
await (CreateSimpleEntityWithAssociationDataAsync());
1087+
1088+
using (var s = OpenSession())
1089+
using (var t = s.BeginTransaction())
1090+
{
1091+
var count = await (s.CreateQuery("delete from SimpleEntityWithAssociation m where not exists (select d from SimpleAssociatedEntity d where d.Owner = m) and m.Name like 'myEntity%'").ExecuteUpdateAsync());
1092+
Assert.That(count, Is.EqualTo(1), "Incorrect delete count");
1093+
await (t.CommitAsync());
1094+
}
1095+
1096+
await (CleanSimpleEntityWithAssociationDataAsync());
1097+
}
1098+
1099+
private async Task CreateSimpleEntityWithAssociationDataAsync(CancellationToken cancellationToken = default(CancellationToken))
1100+
{
1101+
using (var s = OpenSession())
1102+
using (var t = s.BeginTransaction())
1103+
{
1104+
var owner = new SimpleEntityWithAssociation {Name = "myEntity-1"};
1105+
owner.AddAssociation("assoc-1");
1106+
owner.AddAssociation("assoc-2");
1107+
owner.AddAssociation("assoc-3");
1108+
await (s.SaveAsync(owner, cancellationToken));
1109+
var owner2 = new SimpleEntityWithAssociation {Name = "myEntity-2"};
1110+
owner2.AddAssociation("assoc-1");
1111+
owner2.AddAssociation("assoc-2");
1112+
owner2.AddAssociation("assoc-3");
1113+
owner2.AddAssociation("assoc-4");
1114+
await (s.SaveAsync(owner2, cancellationToken));
1115+
var owner3 = new SimpleEntityWithAssociation {Name = "myEntity-3"};
1116+
await (s.SaveAsync(owner3, cancellationToken));
1117+
await (t.CommitAsync(cancellationToken));
1118+
s.Close();
1119+
}
1120+
}
1121+
1122+
private async Task CleanSimpleEntityWithAssociationDataAsync(CancellationToken cancellationToken = default(CancellationToken))
1123+
{
1124+
using (var s = OpenSession())
1125+
using (var t = s.BeginTransaction())
1126+
{
1127+
await (s.CreateQuery("delete SimpleAssociatedEntity").ExecuteUpdateAsync(cancellationToken));
1128+
await (s.CreateQuery("delete SimpleEntityWithAssociation").ExecuteUpdateAsync(cancellationToken));
1129+
await (t.CommitAsync(cancellationToken));
1130+
s.Close();
1131+
}
1132+
}
10821133
#endregion
10831134

10841135
private class TestData

src/NHibernate.Test/Async/Linq/ByMethod/JoinTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,13 @@ public async Task CanJoinOnEntityWithSubclassesAsync()
148148
from o2 in db.Animals.Where(x => x.BodyWeight > 50)
149149
select new {o, o2}).Take(1).ToListAsync());
150150
}
151+
152+
[Test(Description = "GH-2580")]
153+
public async Task CanInnerJoinOnSubclassWithBaseTableReferenceInOnClauseAsync()
154+
{
155+
var result = await ((from o in db.Animals
156+
join o2 in db.Mammals on o.BodyWeight equals o2.BodyWeight
157+
select new { o, o2 }).Take(1).ToListAsync());
158+
}
151159
}
152160
}

src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,5 +788,30 @@ public async Task NullComparedToMemberInitExpressionInWhereClauseAsync()
788788

789789
Assert.That(result.Count, Is.EqualTo(45));
790790
}
791+
792+
public class Specification<T>
793+
{
794+
private Expression<Func<T, bool>> _expression;
795+
796+
public Specification(Expression<Func<T, bool>> expression)
797+
{
798+
_expression = expression;
799+
}
800+
801+
public static implicit operator Expression<Func<T, bool>>(Specification<T> specification)
802+
{
803+
return specification._expression;
804+
}
805+
}
806+
807+
[Test]
808+
public async Task ImplicitConversionInsideWhereSubqueryExpressionAsync()
809+
{
810+
if (!Dialect.SupportsScalarSubSelects)
811+
Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries");
812+
813+
var spec = new Specification<Order>(x => x.Freight > 1000);
814+
await (db.Orders.Where(o => db.Orders.Where(spec).Any(x => x.OrderId == o.OrderId)).ToListAsync());
815+
}
791816
}
792817
}

src/NHibernate.Test/Async/LinqBulkManipulation/Fixture.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,76 @@ public async Task InsertWithClientSideRequirementsThrowsExceptionAsync()
300300
}
301301
}
302302

303+
[Test(Description = "GH2594")]
304+
public async Task InsertIntoWithSubqueryAsync()
305+
{
306+
if(!Dialect.SupportsScalarSubSelects)
307+
Assert.Ignore("Dialect does not support scalar sub-select");
308+
309+
using (var s = OpenSession())
310+
using (var t = s.BeginTransaction())
311+
{
312+
await (s
313+
.Query<Car>()
314+
.InsertIntoAsync(
315+
x => new Pickup
316+
{
317+
Id = -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault(),
318+
Vin = x.Vin,
319+
Owner = x.Owner
320+
}));
321+
322+
await (t.CommitAsync());
323+
}
324+
}
325+
326+
[Test]
327+
public async Task UpdateWithSubqueryAsync()
328+
{
329+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
330+
Assert.Ignore("Not supported by dialect");
331+
332+
using (var s = OpenSession())
333+
using (var t = s.BeginTransaction())
334+
{
335+
await (s
336+
.Query<Car>()
337+
.UpdateAsync(
338+
x => new
339+
{
340+
Id = -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault(),
341+
Vin = x.Vin,
342+
Owner = x.Owner
343+
}));
344+
345+
await (t.CommitAsync());
346+
}
347+
}
348+
349+
[Test]
350+
public async Task MultiTableUpdateWithSubqueryAsync()
351+
{
352+
if (!Dialect.SupportsTemporaryTables)
353+
Assert.Ignore("Cannot perform multi-table updates using dialect not supporting temp tables.");
354+
355+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
356+
Assert.Ignore("Not supported by dialect");
357+
358+
using (var s = OpenSession())
359+
using (var t = s.BeginTransaction())
360+
{
361+
await (s
362+
.Query<Animal>()
363+
.UpdateAsync(
364+
x => new
365+
{
366+
Description = s.Query<DomesticAnimal>().Where(c => c.Id == x.Id).Select(c => c.Description).FirstOrDefault(),
367+
}));
368+
369+
await (t.CommitAsync());
370+
}
371+
}
372+
303373
[Test]
304374
public async Task InsertWithManyToOneAsync()
305375
{
@@ -990,6 +1060,24 @@ public async Task DeleteWithSubqueryAsync()
9901060
}
9911061
}
9921062

1063+
[Test]
1064+
public async Task DeleteWithSubquery2Async()
1065+
{
1066+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
1067+
Assert.Ignore("Not supported by dialect");
1068+
1069+
using (var s = OpenSession())
1070+
using (var t = s.BeginTransaction())
1071+
{
1072+
await (s
1073+
.Query<Car>()
1074+
.Where(x => x.Id == -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault())
1075+
.DeleteAsync());
1076+
1077+
await (t.CommitAsync());
1078+
}
1079+
}
1080+
9931081
[Test]
9941082
public async Task SimpleDeleteOnAnimalAsync()
9951083
{

0 commit comments

Comments
 (0)