Skip to content

Merge 5.3.4 #2593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion releasenotes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
Build 5.3.3
Build 5.3.4
=============================

Release notes - NHibernate - Version 5.3.4

6 issues were resolved in this release.

** Bug

* #2580 InvalidWithClauseException when join polymorphic entity
* #2559 Regression in caching linq query with ThenFetchMany statement.
* #2549 ApplyFilter does not work on join statements in LINQ
* #2537 Unable to cast "System.Linq.Expressions.UnaryExpression" to "System.Linq.Expressions.LambdaExpression".

** Task

* #2578 Add missing possible breaking changes for #2365
* #2587 Release 5.3.4

As part of releasing 5.3.4, one missing 5.3.0 possible breaking change has been added, about
custom method generators for Linq. See 5.3.0 possible breaking changes.

Build 5.3.3
=============================

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

** Bug

Expand Down
8 changes: 8 additions & 0 deletions src/NHibernate.Test/Async/Linq/ByMethod/JoinTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,13 @@ public async Task CanJoinOnEntityWithSubclassesAsync()
from o2 in db.Animals.Where(x => x.BodyWeight > 50)
select new {o, o2}).Take(1).ToListAsync());
}

[Test(Description = "GH-2580")]
public async Task CanInnerJoinOnSubclassWithBaseTableReferenceInOnClauseAsync()
{
var result = await ((from o in db.Animals
join o2 in db.Mammals on o.BodyWeight equals o2.BodyWeight
select new { o, o2 }).Take(1).ToListAsync());
}
}
}
25 changes: 25 additions & 0 deletions src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -788,5 +788,30 @@ public async Task NullComparedToMemberInitExpressionInWhereClauseAsync()

Assert.That(result.Count, Is.EqualTo(45));
}

public class Specification<T>
{
private Expression<Func<T, bool>> _expression;

public Specification(Expression<Func<T, bool>> expression)
{
_expression = expression;
}

public static implicit operator Expression<Func<T, bool>>(Specification<T> specification)
{
return specification._expression;
}
}

[Test]
public async Task ImplicitConversionInsideWhereSubqueryExpressionAsync()
{
if (!Dialect.SupportsScalarSubSelects)
Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries");

var spec = new Specification<Order>(x => x.Freight > 1000);
await (db.Orders.Where(o => db.Orders.Where(spec).Any(x => x.OrderId == o.OrderId)).ToListAsync());
}
}
}
82 changes: 82 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH2549/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System.Linq;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.GH2549
{
using System.Threading.Tasks;
[TestFixture]
public class FixtureAsync : BugTestCase
{
protected override void OnSetUp()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.Save(new Person {Id = 1, Name = "Name"});
s.Save(new Customer {Deleted = false, Name = "Name", Id = 1});
s.Save(new Customer {Deleted = true, Name = "Name", Id = 2});

t.Commit();
}
}

protected override void OnTearDown()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.CreateQuery("delete from System.Object").ExecuteUpdate();
t.Commit();
}
}

[Test]
public async Task EntityJoinFilterLinqAsync()
{
using (var s = OpenSession())
{
var list = await ((from p in s.Query<Person>()
join c in s.Query<Customer>() on p.Name equals c.Name
select p).ToListAsync());

s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);

var filteredList = await ((from p in s.Query<Person>()
join c in s.Query<Customer>() on p.Name equals c.Name
select p).ToListAsync());

Assert.That(list, Has.Count.EqualTo(2));
Assert.That(filteredList, Has.Count.EqualTo(1));
}
}

[Test]
public async Task EntityJoinFilterQueryOverAsync()
{
using (var s = OpenSession())
{
Customer c = null;
Person p = null;
var list = await (s.QueryOver(() => p).JoinEntityAlias(() => c, () => c.Name == p.Name).ListAsync());

s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);

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

Assert.That(list, Has.Count.EqualTo(2));
Assert.That(filteredList, Has.Count.EqualTo(1));
}
}
}
}
156 changes: 156 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH2559/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Linq;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH2559
{
using System.Threading.Tasks;
[TestFixture]
public class ByCodeFixtureAsync : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Person>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.Guid));
rc.Property(x => x.Name);
rc.Property(x => x.Age);
rc.Set(
x => x.Children,
colMap =>
{
colMap.Inverse(true);
colMap.Cascade(Mapping.ByCode.Cascade.DeleteOrphans);
colMap.Cache(c => c.Usage(CacheUsage.ReadWrite));
},
rel => rel.OneToMany());
rc.Set(
x => x.Cars,
colMap =>
{
colMap.Inverse(true);
colMap.Cascade(Mapping.ByCode.Cascade.DeleteOrphans);
colMap.Cache(c => c.Usage(CacheUsage.ReadWrite));
},
rel => rel.OneToMany());
rc.Cache(c => c.Usage(CacheUsage.ReadWrite));
});
mapper.Class<Child>(ch =>
{
ch.Id(x => x.Id, m => m.Generator(Generators.Guid));
ch.Property(x => x.Name);
ch.ManyToOne(c => c.Parent);

ch.Set(
x => x.Pets,
colMap =>
{
colMap.Inverse(true);
colMap.Cascade(Mapping.ByCode.Cascade.DeleteOrphans);
colMap.Cache(c => c.Usage(CacheUsage.ReadWrite));
},
rel => rel.OneToMany());

ch.Cache(c => c.Usage(CacheUsage.ReadWrite));
});
mapper.Class<Pet>(ch =>
{
ch.Id(x => x.Id, m => m.Generator(Generators.Guid));
ch.Property(x => x.Name);
ch.ManyToOne(c => c.Owner);

ch.Cache(c => c.Usage(CacheUsage.ReadWrite));
});
mapper.Class<Car>(ch =>
{
ch.Id(x => x.Id, m => m.Generator(Generators.Guid));
ch.Property(x => x.Name);
ch.ManyToOne(c => c.Owner);

ch.Cache(c => c.Usage(CacheUsage.ReadWrite));
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var person = new Person { Name = "Person 1", Age = 18 };

var car1 = new Car { Name = "Car1", Owner = person };
var car2 = new Car { Name = "Car2", Owner = person };
session.Save(car1);
session.Save(car2);

session.Save(person);
transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.CreateQuery("delete from Pet").ExecuteUpdate();
session.CreateQuery("delete from Child").ExecuteUpdate();
session.CreateQuery("delete from Car").ExecuteUpdate();
session.CreateQuery("delete from Person").ExecuteUpdate();
transaction.Commit();
}
}

[Test]
public async Task TestQueryCachingWithThenFetchManyAsync()
{
Person dbPerson;
Person cachePerson;
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var query =
session
.Query<Person>()
.FetchMany(p => p.Children)
.ThenFetchMany(ch => ch.Pets)
.FetchMany(p => p.Cars) as IQueryable<Person>;

query = query.WithOptions(opt =>
opt.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.SetCacheRegion("Long_Cache"));

dbPerson = (await (query.ToListAsync())).First(); // First time the result will be cached
cachePerson = (await (query.ToListAsync())).First();

await (transaction.CommitAsync());
}

Assert.That(NHibernateUtil.IsInitialized(dbPerson.Cars), Is.True);
Assert.That(NHibernateUtil.IsInitialized(cachePerson.Cars), Is.True);
Assert.That(dbPerson.Cars, Has.Count.EqualTo(2));
Assert.That(cachePerson.Cars, Has.Count.EqualTo(2));

Assert.That(NHibernateUtil.IsInitialized(dbPerson.Children), Is.True);
Assert.That(NHibernateUtil.IsInitialized(cachePerson.Children), Is.True);
Assert.That(dbPerson.Children, Has.Count.EqualTo(0));
Assert.That(cachePerson.Children, Has.Count.EqualTo(0));
}
}
}
8 changes: 8 additions & 0 deletions src/NHibernate.Test/Linq/ByMethod/JoinTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,13 @@ public void CanJoinOnEntityWithSubclasses()
from o2 in db.Animals.Where(x => x.BodyWeight > 50)
select new {o, o2}).Take(1).ToList();
}

[Test(Description = "GH-2580")]
public void CanInnerJoinOnSubclassWithBaseTableReferenceInOnClause()
{
var result = (from o in db.Animals
join o2 in db.Mammals on o.BodyWeight equals o2.BodyWeight
select new { o, o2 }).Take(1).ToList();
}
}
}
25 changes: 25 additions & 0 deletions src/NHibernate.Test/Linq/WhereSubqueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -956,5 +956,30 @@ public void NullComparedToMemberInitExpressionInWhereClause()

Assert.That(result.Count, Is.EqualTo(45));
}

public class Specification<T>
{
private Expression<Func<T, bool>> _expression;

public Specification(Expression<Func<T, bool>> expression)
{
_expression = expression;
}

public static implicit operator Expression<Func<T, bool>>(Specification<T> specification)
{
return specification._expression;
}
}

[Test]
public void ImplicitConversionInsideWhereSubqueryExpression()
{
if (!Dialect.SupportsScalarSubSelects)
Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries");

var spec = new Specification<Order>(x => x.Freight > 1000);
db.Orders.Where(o => db.Orders.Where(spec).Any(x => x.OrderId == o.OrderId)).ToList();
}
}
}
Loading