Skip to content

Commit

Permalink
Merge 5.3.11
Browse files Browse the repository at this point in the history
Discarded changes:
 - UpdateTimestampsCache.cs, see nhibernate#3019
 - packages.csproj, see nhibernate#2984
  • Loading branch information
fredericDelaporte committed Feb 20, 2022
2 parents 502d243 + 211891f commit e85c935
Show file tree
Hide file tree
Showing 48 changed files with 1,036 additions and 113 deletions.
20 changes: 20 additions & 0 deletions doc/reference/modules/configuration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,26 @@ var session = sessions.OpenSession(conn);
</para>
</entry>
</row>
<row>
<entry>
<literal>cache.read_write_lock_factory</literal>
</entry>
<entry>
Specify the cache lock factory to use for read-write cache regions.
Defaults to the built-in <literal>async</literal> cache lock factory.
<para>
<emphasis role="strong">eg.</emphasis>
<literal>async</literal>, or <literal>sync</literal>, or <literal>classname.of.CacheLockFactory, assembly</literal> with custom implementation of <literal>ICacheReadWriteLockFactory</literal>
</para>
<para>
<literal>async</literal> uses a single writer multiple readers locking mechanism supporting asynchronous operations.
</para>
<para>
<literal>sync</literal> uses a single access locking mechanism which will throw on asynchronous
operations but may have better performances than the <literal>async</literal> provider for applications using the .Net Framework (4.8 and below).
</para>
</entry>
</row>
<row>
<entry>
<literal>cache.region_prefix</literal>
Expand Down
27 changes: 26 additions & 1 deletion releasenotes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
Build 5.3.10
Build 5.3.11
=============================

Release notes - NHibernate - Version 5.3.11

12 issues were resolved in this release.

** Bug

* #3005 LINQ: Casting from object to TimeSpan throws
* #2988 Query issues when using not-found='ignore' in entity mapping
* #2965 Fix possible issue with logging for Linq Readonly tests
* #2963 Time is incompatible with bigint for TimeAsTimeSpanType
* #2937 NRE in linq processing of custom components
* #2928 Session.Refresh when entity is IFieldInterceptorAccessor throws a MappingException
* #2904 SQL query result not retrieved from second level cache
* #2876 Schema validation not working with NpgSql v5
* #2862 NHibernate AsyncReaderWriterLock stalls under load
* #2727 The session.Load(obj, id) overload can't handle proxies

** Task

* #3019 Release 5.3.11
* #2984 Bump AsyncGenerator to 0.18.3 for 5.3 branch with fix for .net 6

Build 5.3.10
=============================

Release notes - NHibernate - Version 5.3.10
Expand Down
2 changes: 2 additions & 0 deletions src/AsyncGenerator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@
- conversion: Ignore
anyBaseTypeRule: IsTestCase
executionPhase: PostProviders
- conversion: Ignore
name: SyncOnlyCacheFixture
ignoreDocuments:
- filePathEndsWith: Linq/MathTests.cs
- filePathEndsWith: Linq/ExpressionSessionLeakTest.cs
Expand Down
24 changes: 14 additions & 10 deletions src/NHibernate.Test/Async/CacheTest/CacheFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ namespace NHibernate.Test.CacheTest
{
using System.Threading.Tasks;
[TestFixture]
public class CacheFixtureAsync
public class CacheFixtureAsync: TestCase
{
[Test]
public async Task TestSimpleCacheAsync()
{
await (DoTestCacheAsync(new HashtableCacheProvider()));
}

private CacheKey CreateCacheKey(string text)
protected CacheKey CreateCacheKey(string text)
{
return new CacheKey(text, NHibernateUtil.String, "Foo", null, null);
}

public async Task DoTestCacheAsync(ICacheProvider cacheProvider, CancellationToken cancellationToken = default(CancellationToken))
{
var cache = cacheProvider.BuildCache(typeof(String).FullName, new Dictionary<string, string>());
var cache = (CacheBase) cacheProvider.BuildCache(typeof(String).FullName, new Dictionary<string, string>());

long longBefore = Timestamper.Next();

Expand All @@ -44,8 +44,7 @@ private CacheKey CreateCacheKey(string text)

await (Task.Delay(15, cancellationToken));

ICacheConcurrencyStrategy ccs = new ReadWriteCache();
ccs.Cache = cache;
ICacheConcurrencyStrategy ccs = CreateCache(cache);

// cache something
CacheKey fooKey = CreateCacheKey("foo");
Expand Down Expand Up @@ -155,12 +154,17 @@ private CacheKey CreateCacheKey(string text)
public async Task MinValueTimestampAsync()
{
var cache = new HashtableCacheProvider().BuildCache("region", new Dictionary<string, string>());
ICacheConcurrencyStrategy strategy = new ReadWriteCache();
strategy.Cache = cache;

await (DoTestMinValueTimestampOnStrategyAsync(cache, new ReadWriteCache()));
await (DoTestMinValueTimestampOnStrategyAsync(cache, new NonstrictReadWriteCache()));
await (DoTestMinValueTimestampOnStrategyAsync(cache, new ReadOnlyCache()));
await (DoTestMinValueTimestampOnStrategyAsync(cache, CreateCache(cache)));
await (DoTestMinValueTimestampOnStrategyAsync(cache, CreateCache(cache, CacheFactory.NonstrictReadWrite)));
await (DoTestMinValueTimestampOnStrategyAsync(cache, CreateCache(cache, CacheFactory.ReadOnly)));
}

protected virtual ICacheConcurrencyStrategy CreateCache(CacheBase cache, string strategy = CacheFactory.ReadWrite)
{
return CacheFactory.CreateCache(strategy, cache, Sfi.Settings);
}

protected override string[] Mappings => Array.Empty<string>();
}
}
12 changes: 12 additions & 0 deletions src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,23 @@ public async Task NullableEntityProjectionAsync()
from x2 in session.Query<NullableOwner>()
where x == x2 && x.ManyToOne == null && x.OneToOne.Name == null
select x2).ToListAsync());

var validManyToOne = new OneToOneEntity{Name = "valid"};
await (session.SaveAsync(validManyToOne));
nullableOwner2.ManyToOne = validManyToOne;
await (session.FlushAsync());

//GH-2988
var withNullOrValidList = await (session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == validManyToOne.Id || x.ManyToOne == null).ToListAsync());
var withNullOrValidList2 = await (session.Query<NullableOwner>().Where(x => x.ManyToOne == null || x.ManyToOne.Id == validManyToOne.Id).ToListAsync());

Assert.That(fullList.Count, Is.EqualTo(2));
Assert.That(withValidManyToOneList.Count, Is.EqualTo(0));
Assert.That(withValidManyToOneList2.Count, Is.EqualTo(0));
Assert.That(withNullManyToOneList.Count, Is.EqualTo(2));
Assert.That(withNullManyToOneJoinedList.Count, Is.EqualTo(2));
Assert.That(withNullOrValidList.Count, Is.EqualTo(2));
Assert.That(withNullOrValidList2.Count, Is.EqualTo(2));
}
}

Expand Down
14 changes: 13 additions & 1 deletion src/NHibernate.Test/Async/Linq/CustomExtensionsExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
//------------------------------------------------------------------------------


using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using NHibernate.Cfg;
using NHibernate.DomainModel.Northwind.Entities;
using NHibernate.Hql.Ast;
using NHibernate.Linq.Functions;
Expand Down Expand Up @@ -42,6 +42,18 @@ public async Task CanUseObjectEqualsAsync()
Assert.That(users.All(c => c.NullableEnum1 == EnumStoredAsString.Medium), Is.True);
}

[Test(Description = "GH-2963")]
public async Task CanUseComparisonWithExtensionOnMappedPropertyAsync()
{
if (!TestDialect.SupportsTime)
{
Assert.Ignore("Time type is not supported");
}

var time = DateTime.UtcNow.GetTime();
await (db.Users.Where(u => u.RegisteredAt.GetTime() > time).Select(u => u.Id).ToListAsync());
}

[Test]
public async Task CanUseMyCustomExtensionAsync()
{
Expand Down
97 changes: 97 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH2727/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
// <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;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH2727
{
using System.Threading.Tasks;
/// <summary>
/// Fixture using 'by code' mappings
/// </summary>
[TestFixture]
public class LazyPropByCodeFixtureAsync : TestCaseMappingByCode
{
private Guid id1;
private Guid id2;

protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Entity>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Property(x => x.LazyProp, m => m.Lazy(true));
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var e1 = new Entity { Name = "Bob" };
session.Save(e1);

var e2 = new Entity { Name = "Sally" };
session.Save(e2);

transaction.Commit();
id1 = e1.Id;
id2 = e2.Id;
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
// The HQL delete does all the job inside the database without loading the entities, but it does
// not handle delete order for avoiding violating constraints if any. Use
// session.Delete("from System.Object");
// instead if in need of having NHbernate ordering the deletes, but this will cause
// loading the entities in the session.
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}
}

[Test]
public async Task CanLoadUsingInstanceAsync()
{
using (var s = OpenSession())
{
var e1 = await (s.LoadAsync<Entity>(id1));
await (s.LoadAsync(e1, id2));
}
}

[Test(Description = "GH-2928")]
public async Task CanSessionRefreshEntityWithLazyPropertiesAsync()
{
using (var s = OpenSession())
{
var e1 = await (s.GetAsync<Entity>(id1));
await (s.RefreshAsync(e1));
s.Clear();
await (s.RefreshAsync(e1));
}
}
}
}
71 changes: 71 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH3005/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <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;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.GH3005
{
using System.Threading.Tasks;
[TestFixture]
public class ByCodeFixtureAsync : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Entity>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Property(x => x.Duration);
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var e1 = new Entity { Name = "Bob", Duration = TimeSpan.FromMinutes(1) };
session.Save(e1);

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}
}

[Test]
public async Task CanCastFromObjectAsync()
{
using (var session = OpenSession())
{
var result = await (session.Query<Entity>().Select(x => (TimeSpan)(object)x.Duration).FirstOrDefaultAsync());

Assert.That(result, Is.EqualTo(TimeSpan.FromMinutes(1)));
}
}
}
}
Loading

0 comments on commit e85c935

Please sign in to comment.