Skip to content

Commit 8141d63

Browse files
authored
Merge branch 'master' into comp-id/master
2 parents 9ff9634 + 67d06ee commit 8141d63

31 files changed

+278
-132
lines changed

src/NHibernate.Test/Async/VersionTest/Db/DbVersionFixture.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public async System.Threading.Tasks.Task CollectionVersionAsync()
5252
admin = await (s.GetAsync<Group>(admin.Id));
5353
guy.Groups.Add(admin);
5454
admin.Users.Add(guy);
55+
guy.NoOptimisticLock = "changed";
5556
await (t.CommitAsync());
5657
s.Close();
5758

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using NHibernate.Id;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.IdGen.GuidComb;
6+
7+
[TestFixture]
8+
public class GuidCombFixture
9+
{
10+
class GuidCombGeneratorEx : GuidCombGenerator
11+
{
12+
public static Guid Generate(string guid, DateTime utcNow) => GenerateComb(Guid.Parse(guid), utcNow);
13+
}
14+
15+
[Test]
16+
public void CanGenerateSequentialGuid()
17+
{
18+
Assert.AreEqual(Guid.Parse("076a04fa-ef4e-4093-8479-b0e10103cdc5"),
19+
GuidCombGeneratorEx.Generate(
20+
"076a04fa-ef4e-4093-8479-8599e96f14cf",
21+
new DateTime(2023, 12, 23, 15, 45, 55, DateTimeKind.Utc)),
22+
"seed: 076a04fa");
23+
24+
Assert.AreEqual(Guid.Parse("81162ee2-a4cb-4611-9327-d61f0137e5b6"),
25+
GuidCombGeneratorEx.Generate(
26+
"81162ee2-a4cb-4611-9327-23bbda36176c",
27+
new DateTime(2050, 01, 29, 18, 55, 35, DateTimeKind.Utc)),
28+
"seed: 81162ee2");
29+
30+
}
31+
32+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH3657
4+
{
5+
class Entity
6+
{
7+
public virtual Guid Id { get; set; }
8+
public virtual string Name { get; set; }
9+
}
10+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using log4net;
2+
using NHibernate.Cfg;
3+
using NHibernate.Impl;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.NHSpecificTest.GH3657
7+
{
8+
[TestFixture]
9+
public class Fixture
10+
{
11+
private static readonly ILog _log = LogManager.GetLogger(typeof(Fixture));
12+
private const string TestSessionFactoryName = "TestName";
13+
14+
private Configuration _cfg;
15+
private ISessionFactory _builtSessionFactory;
16+
17+
[OneTimeSetUp]
18+
public void TestFixtureSetUp()
19+
{
20+
_cfg = TestConfigurationHelper.GetDefaultConfiguration();
21+
var type = GetType();
22+
_cfg.AddResource(type.Namespace + ".Mappings.hbm.xml", type.Assembly);
23+
_cfg.SetProperty(Environment.SessionFactoryName, TestSessionFactoryName);
24+
}
25+
26+
[TearDown]
27+
public void TearDown()
28+
{
29+
_builtSessionFactory?.Dispose();
30+
_builtSessionFactory = null;
31+
}
32+
33+
private ISessionFactory SessionFactoryBuilder()
34+
{
35+
Assert.That(_builtSessionFactory, Is.Null, "SessionFactory was already built");
36+
37+
_builtSessionFactory = _cfg.BuildSessionFactory();
38+
_log.Info("Successfully built session factory");
39+
40+
return _builtSessionFactory;
41+
}
42+
43+
[Test]
44+
public void GetOrAddTwice()
45+
{
46+
var factory = SessionFactoryObjectFactory.GetOrBuildNamedInstance(TestSessionFactoryName, SessionFactoryBuilder);
47+
Assert.That(factory, Is.Not.Null, "Failed to get the factory once");
48+
49+
var factory2 = SessionFactoryObjectFactory.GetOrBuildNamedInstance(TestSessionFactoryName, SessionFactoryBuilder);
50+
Assert.That(factory2, Is.Not.Null, "Failed to get the factory twice");
51+
Assert.That(factory, Is.SameAs(factory2), "The two factories should be the same");
52+
}
53+
}
54+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
3+
namespace="NHibernate.Test.NHSpecificTest.GH3657">
4+
5+
<class name="Entity">
6+
<id name="Id" generator="guid.comb"/>
7+
<property name="Name"/>
8+
</class>
9+
10+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<PackageReference Include="NHibernate.Caches.CoreDistributedCache.Memory" Version="5.9.0" />
6969
<PackageReference Include="NHibernate.Caches.Util.JsonSerializer" Version="5.9.0" />
7070
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.117" />
71-
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.14" />
71+
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.0.2" />
7272
<PackageReference Include="NSubstitute" Version="5.1.0" />
7373
<PackageReference Include="NUnit" Version="3.14.0" />
7474
<PackageReference Include="NUnit.Analyzers" Version="4.2.0" />

src/NHibernate.Test/VersionTest/Db/DbVersionFixture.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public void CollectionVersion()
4242
admin = s.Get<Group>(admin.Id);
4343
guy.Groups.Add(admin);
4444
admin.Users.Add(guy);
45+
guy.NoOptimisticLock = "changed";
4546
t.Commit();
4647
s.Close();
4748

src/NHibernate.Test/VersionTest/Db/User.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ public class User
1111

1212
public virtual string Username { get; set; }
1313

14+
public virtual string NoOptimisticLock { get; set; }
15+
1416
public virtual ISet<Group> Groups { get; set; }
1517

1618
public virtual ISet<Permission> Permissions { get; set; }
1719
}
18-
}
20+
}

src/NHibernate.Test/VersionTest/Db/User.hbm.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8" ?>
1+
<?xml version="1.0" encoding="utf-8" ?>
22
<!--
33
Demonstrates how to control the optimistic locking behavior
44
of a collection (do changes to the collection result in
@@ -14,6 +14,7 @@
1414
</id>
1515
<timestamp name="Timestamp" column="ts" source="db"/>
1616
<property name="Username" column="user_name" type="string" unique="true"/>
17+
<property name="NoOptimisticLock" column="no_optimistic_lock" type="string" optimistic-lock="false"/>
1718
<set name="Groups" table="db_vers_user_group" batch-size="9" inverse="true" optimistic-lock="true" lazy="true" cascade="none" >
1819
<key column="user_id"/>
1920
<many-to-many column="group_id" class="Group" lazy="false" fetch="join" />
@@ -45,4 +46,4 @@
4546
<property name="Context" column="ctx" type="string"/>
4647
<property name="Access" column="priv" type="string"/>
4748
</class>
48-
</hibernate-mapping>
49+
</hibernate-mapping>

src/NHibernate/Async/Event/Default/DefaultFlushEntityEventListener.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -336,33 +336,35 @@ private async Task<object> GetNextVersionAsync(FlushEntityEvent @event, Cancella
336336
/// to synchronize its state to the database. Modifies the event by side-effect!
337337
/// Note: this method is quite slow, avoid calling if possible!
338338
/// </summary>
339-
protected Task<bool> IsUpdateNecessaryAsync(FlushEntityEvent @event, CancellationToken cancellationToken)
339+
protected async Task<bool> IsUpdateNecessaryAsync(FlushEntityEvent @event, CancellationToken cancellationToken)
340340
{
341-
if (cancellationToken.IsCancellationRequested)
342-
{
343-
return Task.FromCanceled<bool>(cancellationToken);
344-
}
341+
cancellationToken.ThrowIfCancellationRequested();
345342
IEntityPersister persister = @event.EntityEntry.Persister;
346343
Status status = @event.EntityEntry.Status;
347344

348345
if (!@event.DirtyCheckPossible)
349346
{
350-
return Task.FromResult<bool>(true);
347+
return true;
351348
}
352349
else
353350
{
351+
// call to HasDirtyCollections must not be optimized away because of its side effect
352+
bool hasDirtyCollections = await (HasDirtyCollectionsAsync(@event, persister, status, cancellationToken)).ConfigureAwait(false);
353+
354354
int[] dirtyProperties = @event.DirtyProperties;
355-
if (dirtyProperties != null && dirtyProperties.Length != 0)
356-
{
357-
return Task.FromResult<bool>(true); //TODO: suck into event class
358-
}
359-
else
360-
{
361-
return HasDirtyCollectionsAsync(@event, persister, status, cancellationToken);
362-
}
355+
return dirtyProperties != null && dirtyProperties.Length != 0 || hasDirtyCollections;
363356
}
364357
}
365358

359+
/// <summary>
360+
/// Check if there are any dirty collections.
361+
/// Has a side effect of setting the HasDirtyCollection property of the event.
362+
/// </summary>
363+
/// <param name="event"></param>
364+
/// <param name="persister"></param>
365+
/// <param name="status"></param>
366+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
367+
/// <returns></returns>
366368
private async Task<bool> HasDirtyCollectionsAsync(FlushEntityEvent @event, IEntityPersister persister, Status status, CancellationToken cancellationToken)
367369
{
368370
cancellationToken.ThrowIfCancellationRequested();

0 commit comments

Comments
 (0)