diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs new file mode 100644 index 0000000000..7f40824898 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs @@ -0,0 +1,130 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System.Linq; +using NHibernate.Cfg; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Linq; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH3643 +{ + using System.Threading.Tasks; + using System.Threading; + [TestFixture] + public class FixtureByCodeAsync : TestCaseMappingByCode + { + protected override void Configure(Configuration configuration) + { + configuration.SetProperty(Environment.UseQueryCache, "true"); + configuration.SetProperty(Environment.GenerateStatistics, "true"); + } + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Bag( + x => x.Children, + m => + { + m.Access(Accessor.Field); + m.Key(k => k.Column("EntityId")); + }, + r => r.OneToMany()); + + rc.Cache( + cm => + { + cm.Include(CacheInclude.All); + cm.Usage(CacheUsage.ReadWrite); + }); + }); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Cache( + cm => + { + cm.Include(CacheInclude.All); + cm.Usage(CacheUsage.ReadWrite); + }); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + protected override void OnSetUp() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + + session.CreateSQLQuery( + "INSERT INTO Entity (Id) VALUES (0)" + ).ExecuteUpdate(); + + session.CreateSQLQuery( + "INSERT INTO ChildEntity (Id, EntityId) VALUES (0, 0)" + ).ExecuteUpdate(); + + session.CreateSQLQuery( + "INSERT INTO ChildEntity (Id, EntityId) VALUES (1, 0)" + ).ExecuteUpdate(); + + transaction.Commit(); + } + + protected override void OnTearDown() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + + session.CreateSQLQuery("DELETE FROM ChildEntity").ExecuteUpdate(); + session.CreateSQLQuery("DELETE FROM Entity").ExecuteUpdate(); + + transaction.Commit(); + } + + [Test] + public async Task LoadsEntityWithEnumIdAndChildrenUsingQueryCacheAsync() + { + await (LoadEntityWithQueryCacheAsync()); // warm up cache + + var entity = await (LoadEntityWithQueryCacheAsync()); + + Assert.That(entity.Children.Count(), Is.EqualTo(2)); + + Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count"); + Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count"); + Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count"); + } + + private async Task LoadEntityWithQueryCacheAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + var entity = (await (session + .Query() + .FetchMany(x => x.Children) + .WithOptions(opt => opt.SetCacheable(true)) + .ToListAsync(cancellationToken)))[0]; + + await (transaction.CommitAsync(cancellationToken)); + return entity; + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs new file mode 100644 index 0000000000..60a3de3c86 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +// ReSharper disable CollectionNeverUpdated.Local +// ReSharper disable UnassignedGetOnlyAutoProperty + +namespace NHibernate.Test.NHSpecificTest.GH3643 +{ + class Entity + { + private readonly ICollection _children = new List(); + public virtual EntityId Id { get; protected set; } + public virtual IEnumerable Children => _children.AsEnumerable(); + } + + class ChildEntity + { + public virtual int Id { get; protected set; } + } + + enum EntityId + { + Id1, + Id2 + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs new file mode 100644 index 0000000000..c2694e3b63 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs @@ -0,0 +1,118 @@ +using System.Linq; +using NHibernate.Cfg; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Linq; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH3643 +{ + [TestFixture] + public class FixtureByCode : TestCaseMappingByCode + { + protected override void Configure(Configuration configuration) + { + configuration.SetProperty(Environment.UseQueryCache, "true"); + configuration.SetProperty(Environment.GenerateStatistics, "true"); + } + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Bag( + x => x.Children, + m => + { + m.Access(Accessor.Field); + m.Key(k => k.Column("EntityId")); + }, + r => r.OneToMany()); + + rc.Cache( + cm => + { + cm.Include(CacheInclude.All); + cm.Usage(CacheUsage.ReadWrite); + }); + }); + + mapper.Class( + rc => + { + rc.Id(x => x.Id); + rc.Cache( + cm => + { + cm.Include(CacheInclude.All); + cm.Usage(CacheUsage.ReadWrite); + }); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + protected override void OnSetUp() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + + session.CreateSQLQuery( + "INSERT INTO Entity (Id) VALUES (0)" + ).ExecuteUpdate(); + + session.CreateSQLQuery( + "INSERT INTO ChildEntity (Id, EntityId) VALUES (0, 0)" + ).ExecuteUpdate(); + + session.CreateSQLQuery( + "INSERT INTO ChildEntity (Id, EntityId) VALUES (1, 0)" + ).ExecuteUpdate(); + + transaction.Commit(); + } + + protected override void OnTearDown() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + + session.CreateSQLQuery("DELETE FROM ChildEntity").ExecuteUpdate(); + session.CreateSQLQuery("DELETE FROM Entity").ExecuteUpdate(); + + transaction.Commit(); + } + + [Test] + public void LoadsEntityWithEnumIdAndChildrenUsingQueryCache() + { + LoadEntityWithQueryCache(); // warm up cache + + var entity = LoadEntityWithQueryCache(); + + Assert.That(entity.Children.Count(), Is.EqualTo(2)); + + Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count"); + Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count"); + Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count"); + } + + private Entity LoadEntityWithQueryCache() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + var entity = session + .Query() + .FetchMany(x => x.Children) + .WithOptions(opt => opt.SetCacheable(true)) + .ToList()[0]; + + transaction.Commit(); + return entity; + } + } +} diff --git a/src/NHibernate.sln.DotSettings b/src/NHibernate.sln.DotSettings index d78384192e..b77ef433c2 100644 --- a/src/NHibernate.sln.DotSettings +++ b/src/NHibernate.sln.DotSettings @@ -21,6 +21,9 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="_" Suffix="" Style="aaBb" /></Policy> True True True @@ -29,6 +32,7 @@ True True True + True True True True