Skip to content

NH-3372: Enabled use of generated properties in combination with custom ... #186

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 2 commits into from
Feb 22, 2015
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
9 changes: 9 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3372/Entity.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
47 changes: 47 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3372/Fixture.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}

}
}
21 changes: 21 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3372/Mappings.hbm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernate.Test"
namespace="NHibernate.Test.NHSpecificTest.NH3372">

<class name="Entity" table="entity" lazy="false">
<id name="Id" column="id" generator="native" />
<property name="ShardId" generated="always" insert="false" update="false" />
<property name="Content" column="content" />
<loader query-ref="LoadEntity" />
</class>

<sql-query name="LoadEntity" xml:space="preserve">
<return class="Entity" alias="e" />
SELECT id AS {e.Id}
, DB_NAME() AS {e.ShardId}
, content AS {e.Content}
FROM entity
WHERE id = ?
</sql-query>
</hibernate-mapping>
5 changes: 2 additions & 3 deletions src/NHibernate.Test/NHSpecificTest/NH3570/BiFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using NUnit.Framework;
using SharpTestsEx;

namespace NHibernate.Test.NHSpecificTest.NH3570
{
Expand Down Expand Up @@ -29,8 +28,8 @@ public void ShouldNotSaveRemoveChild()
{
using (s.BeginTransaction())
{
s.Get<BiParent>(id).Children.Count.Should().Be.EqualTo(1);
s.CreateCriteria<BiChild>().List().Count.Should().Be.EqualTo(1);
Assert.That(s.Get<BiParent>(id).Children.Count, Is.EqualTo(1));
Assert.That(s.CreateCriteria<BiChild>().List().Count, Is.EqualTo(1));
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/NHibernate.Test/NHSpecificTest/NH3570/UniFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using NUnit.Framework;
using SharpTestsEx;

namespace NHibernate.Test.NHSpecificTest.NH3570
{
Expand Down Expand Up @@ -29,8 +28,8 @@ public void ShouldNotSaveRemoveChild()
{
using (s.BeginTransaction())
{
s.Get<UniParent>(id).Children.Count.Should().Be.EqualTo(1);
s.CreateCriteria<UniChild>().List().Count.Should().Be.EqualTo(1);
Assert.That(s.Get<UniParent>(id).Children.Count, Is.EqualTo(1));
Assert.That(s.CreateCriteria<UniChild>().List().Count, Is.EqualTo(1));
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/NHibernate.Test/NHibernate.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,8 @@
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
<Compile Include="Linq\ByMethod\DistinctTests.cs" />
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
<Compile Include="NHSpecificTest\NH3372\Entity.cs" />
<Compile Include="NHSpecificTest\NH3372\Fixture.cs" />
<Compile Include="NHSpecificTest\NH3487\Entity.cs" />
<Compile Include="NHSpecificTest\NH3487\Fixture.cs" />
<Compile Include="NHSpecificTest\NH3570\BiFixture.cs" />
Expand Down Expand Up @@ -3068,6 +3070,7 @@
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
</ItemGroup>
<ItemGroup>
<Content Include="NHSpecificTest\NH3372\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH3570\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH3455\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH3590\Mappings.hbm.xml" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using NHibernate.Mapping.ByCode.Conformist;
using NHibernate.Linq;
using NUnit.Framework;
using SharpTestsEx;

namespace NHibernate.Test.Stateless.FetchingLazyCollections
{
Expand Down Expand Up @@ -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<Family<Reptile>> rf = s.Query<Family<Reptile>>().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();
}
Expand Down
59 changes: 52 additions & 7 deletions src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
{
Expand All @@ -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);
Expand All @@ -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; }
Expand Down