diff --git a/src/NHibernate.Test/NHSpecificTest/NH3372/Entity.cs b/src/NHibernate.Test/NHSpecificTest/NH3372/Entity.cs
new file mode 100644
index 00000000000..5127f405983
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/NH3372/Entity.cs
@@ -0,0 +1,9 @@
+namespace NHibernate.Test.NHSpecificTest.NH3372
+{
+ public class Entity
+ {
+ public int Id { get; set; }
+ public string ShardId { get; set; }
+ public string Content { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3372/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3372/Fixture.cs
new file mode 100644
index 00000000000..668c0085aaa
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/NH3372/Fixture.cs
@@ -0,0 +1,47 @@
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH3372
+{
+ [TestFixture]
+ public class Fixture : BugTestCase
+ {
+ protected override bool AppliesTo(Dialect.Dialect dialect)
+ {
+ return dialect is NHibernate.Dialect.MsSql2000Dialect;
+ }
+
+ [Test]
+ public void CanGeneratePropertyOnInsertOfEntityWithCustomLoader()
+ {
+ using (var session = OpenSession())
+ using (session.BeginTransaction())
+ {
+ var entity = new Entity { Content = "Some text" };
+ session.Save(entity);
+ session.Flush();
+
+ Assert.That(entity.ShardId, Is.Not.Null & Has.Length.GreaterThan(0));
+ }
+ }
+
+ [Test]
+ public void CanGeneratePropertyOnUpdateOfEntityWithCustomLoader()
+ {
+ using (var session = OpenSession())
+ using (session.BeginTransaction())
+ {
+ var entity = new Entity { Content = "Some text" };
+ session.Save(entity);
+ session.Flush();
+
+ entity.ShardId = null;
+ entity.Content = "Some other text";
+ session.Update(entity);
+ session.Flush();
+
+ Assert.That(entity.ShardId, Is.Not.Null & Has.Length.GreaterThan(0));
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3372/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/NH3372/Mappings.hbm.xml
new file mode 100644
index 00000000000..5d4f58029e6
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/NH3372/Mappings.hbm.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ SELECT id AS {e.Id}
+ , DB_NAME() AS {e.ShardId}
+ , content AS {e.Content}
+ FROM entity
+ WHERE id = ?
+
+
\ No newline at end of file
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3570/BiFixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3570/BiFixture.cs
index 6e75293c049..5222dbeabdc 100644
--- a/src/NHibernate.Test/NHSpecificTest/NH3570/BiFixture.cs
+++ b/src/NHibernate.Test/NHSpecificTest/NH3570/BiFixture.cs
@@ -1,6 +1,5 @@
using System;
using NUnit.Framework;
-using SharpTestsEx;
namespace NHibernate.Test.NHSpecificTest.NH3570
{
@@ -29,8 +28,8 @@ public void ShouldNotSaveRemoveChild()
{
using (s.BeginTransaction())
{
- s.Get(id).Children.Count.Should().Be.EqualTo(1);
- s.CreateCriteria().List().Count.Should().Be.EqualTo(1);
+ Assert.That(s.Get(id).Children.Count, Is.EqualTo(1));
+ Assert.That(s.CreateCriteria().List().Count, Is.EqualTo(1));
}
}
}
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3570/UniFixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3570/UniFixture.cs
index 749eddbfe42..b366e65dc91 100644
--- a/src/NHibernate.Test/NHSpecificTest/NH3570/UniFixture.cs
+++ b/src/NHibernate.Test/NHSpecificTest/NH3570/UniFixture.cs
@@ -1,6 +1,5 @@
using System;
using NUnit.Framework;
-using SharpTestsEx;
namespace NHibernate.Test.NHSpecificTest.NH3570
{
@@ -29,8 +28,8 @@ public void ShouldNotSaveRemoveChild()
{
using (s.BeginTransaction())
{
- s.Get(id).Children.Count.Should().Be.EqualTo(1);
- s.CreateCriteria().List().Count.Should().Be.EqualTo(1);
+ Assert.That(s.Get(id).Children.Count, Is.EqualTo(1));
+ Assert.That(s.CreateCriteria().List().Count, Is.EqualTo(1));
}
}
}
diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj
index c60b89ab659..90cd4a138a0 100644
--- a/src/NHibernate.Test/NHibernate.Test.csproj
+++ b/src/NHibernate.Test/NHibernate.Test.csproj
@@ -691,6 +691,8 @@
+
+
@@ -3068,6 +3070,7 @@
+
diff --git a/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs b/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs
index bc4161a0a1a..f4b2218640f 100644
--- a/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs
+++ b/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs
@@ -6,7 +6,6 @@
using NHibernate.Mapping.ByCode.Conformist;
using NHibernate.Linq;
using NUnit.Framework;
-using SharpTestsEx;
namespace NHibernate.Test.Stateless.FetchingLazyCollections
{
@@ -138,13 +137,13 @@ public void ShouldWorkLoadingComplexEntities()
Assert.That(hf.Count, Is.EqualTo(1));
Assert.That(hf[0].Father.Name, Is.EqualTo(humanFather));
Assert.That(hf[0].Mother.Name, Is.EqualTo(humanMother));
- NHibernateUtil.IsInitialized(hf[0].Childs).Should("Lazy collection should be initialized").Be.True();
+ Assert.That(NHibernateUtil.IsInitialized(hf[0].Childs), Is.True, "Lazy collection should be initialized");
IList> rf = s.Query>().FetchMany(f => f.Childs).ToList();
Assert.That(rf.Count, Is.EqualTo(1));
Assert.That(rf[0].Father.Description, Is.EqualTo(crocodileFather));
Assert.That(rf[0].Mother.Description, Is.EqualTo(crocodileMother));
- NHibernateUtil.IsInitialized(hf[0].Childs).Should("Lazy collection should be initialized").Be.True();
+ Assert.That(NHibernateUtil.IsInitialized(hf[0].Childs), Is.True, "Lazy collection should be initialized");
tx.Commit();
}
diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
index 62ed069d4b2..9ac97831c39 100644
--- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
+++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
@@ -4026,7 +4026,23 @@ public void ProcessInsertGeneratedProperties(object id, object entity, object[]
{
throw new AssertionFailure("no insert-generated properties");
}
- ProcessGeneratedProperties(id, entity, state, session, sqlInsertGeneratedValuesSelectString, PropertyInsertGenerationInclusions);
+
+ session.Batcher.ExecuteBatch(); //force immediate execution of the insert
+
+ if (loaderName == null)
+ {
+ ProcessGeneratedPropertiesWithGeneratedSql(id, entity, state, session, sqlInsertGeneratedValuesSelectString, PropertyInsertGenerationInclusions);
+ }
+ else
+ {
+ ProcessGeneratedPropertiesWithLoader(id, entity, session);
+
+ // The loader has added the entity to the first-level cache. We must remove
+ // the entity from the first-level cache to avoid problems in the Save or SaveOrUpdate
+ // event listeners, which don't expect the entity to already be present in the
+ // first-level cache.
+ session.PersistenceContext.RemoveEntity(session.GenerateEntityKey(id, this));
+ }
}
public void ProcessUpdateGeneratedProperties(object id, object entity, object[] state, ISessionImplementor session)
@@ -4035,14 +4051,25 @@ public void ProcessUpdateGeneratedProperties(object id, object entity, object[]
{
throw new AssertionFailure("no update-generated properties");
}
- ProcessGeneratedProperties(id, entity, state, session, sqlUpdateGeneratedValuesSelectString, PropertyUpdateGenerationInclusions);
+
+ session.Batcher.ExecuteBatch(); //force immediate execution of the update
+
+ if (loaderName == null)
+ {
+ ProcessGeneratedPropertiesWithGeneratedSql(id, entity, state, session, sqlUpdateGeneratedValuesSelectString, PropertyUpdateGenerationInclusions);
+ }
+ else
+ {
+ // Remove entity from first-level cache to ensure that loader fetches fresh data from database.
+ // The loader will ensure that the same entity is added back to the first-level cache.
+ session.PersistenceContext.RemoveEntity(session.GenerateEntityKey(id, this));
+ ProcessGeneratedPropertiesWithLoader(id, entity, session);
+ }
}
- private void ProcessGeneratedProperties(object id, object entity, object[] state,
- ISessionImplementor session, SqlString selectionSQL, ValueInclusion[] includeds)
+ private void ProcessGeneratedPropertiesWithGeneratedSql(object id, object entity, object[] state,
+ ISessionImplementor session, SqlString selectionSQL, ValueInclusion[] generationInclusions)
{
- session.Batcher.ExecuteBatch(); //force immediate execution of the insert
-
using (new SessionIdLoggingContext(session.SessionId))
try
{
@@ -4060,7 +4087,7 @@ private void ProcessGeneratedProperties(object id, object entity, object[] state
}
for (int i = 0; i < PropertySpan; i++)
{
- if (includeds[i] != ValueInclusion.None)
+ if (generationInclusions[i] != ValueInclusion.None)
{
object hydratedState = PropertyTypes[i].Hydrate(rs, GetPropertyAliases(string.Empty, i), session, entity);
state[i] = PropertyTypes[i].ResolveIdentifier(hydratedState, session, entity);
@@ -4087,6 +4114,24 @@ private void ProcessGeneratedProperties(object id, object entity, object[] state
}
}
+ private void ProcessGeneratedPropertiesWithLoader(object id, object entity, ISessionImplementor session)
+ {
+ var query = (AbstractQueryImpl)session.GetNamedQuery(loaderName);
+ if (query.HasNamedParameters)
+ {
+ query.SetParameter(query.NamedParameters[0], id, this.IdentifierType);
+ }
+ else
+ {
+ query.SetParameter(0, id, this.IdentifierType);
+ }
+ query.SetOptionalId(id);
+ query.SetOptionalEntityName(this.EntityName);
+ query.SetOptionalObject(entity);
+ query.SetFlushMode(FlushMode.Never);
+ query.List();
+ }
+
public bool HasSubselectLoadableCollections
{
get { return hasSubselectLoadableCollections; }