|
From: <fab...@us...> - 2010-09-26 16:54:22
|
Revision: 5224
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5224&view=rev
Author: fabiomaulo
Date: 2010-09-26 16:54:16 +0000 (Sun, 26 Sep 2010)
Log Message:
-----------
Fix NH-2348 (thanks to Patrick Earl for the idea)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/
trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Domain.cs
trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Mappings.hbm.xml
trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/PolymorphicGetAndLoadTest.cs
Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs 2010-09-26 14:26:22 UTC (rev 5223)
+++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultLoadEventListener.cs 2010-09-26 16:54:16 UTC (rev 5224)
@@ -1,6 +1,6 @@
using System;
using System.Diagnostics;
-
+using System.Text;
using NHibernate.Cache;
using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
@@ -36,7 +36,7 @@
}
else
{
- persister = source.Factory.GetEntityPersister(@event.EntityClassName);
+ persister = GetEntityPersister(source.Factory, @event.EntityClassName);
}
if (persister == null)
@@ -384,7 +384,7 @@
}
if (options.IsAllowNulls)
{
- IEntityPersister persister = @event.Session.Factory.GetEntityPersister(@event.EntityClassName);
+ IEntityPersister persister = GetEntityPersister(@event.Session.Factory, @event.EntityClassName);
if (!persister.IsInstance(old, @event.Session.EntityMode))
{
return InconsistentRTNClassMarker;
@@ -493,5 +493,32 @@
}
return result;
}
+
+ protected virtual IEntityPersister GetEntityPersister(ISessionFactoryImplementor factory, string entityName)
+ {
+ // Check for an exact match.
+ IEntityPersister persister = factory.TryGetEntityPersister(entityName);
+ if (persister != null)
+ {
+ return persister;
+ }
+
+ // Couldn't find persister through exact name, try finding a single implementing class.
+ string[] implementors = factory.GetImplementors(entityName);
+ if (implementors.Length > 1)
+ {
+ var messageBuilder = new StringBuilder(512);
+ messageBuilder.AppendLine(string.Format("Ambiguous persister for {0} implemented by more than one hierarchy: ",
+ entityName));
+ Array.ForEach(implementors, s=> messageBuilder.AppendLine(s));
+
+ throw new HibernateException(messageBuilder.ToString());
+ }
+ if (implementors.Length == 0)
+ {
+ return null;
+ }
+ return factory.GetEntityPersister(implementors[0]);
+ }
}
}
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-09-26 14:26:22 UTC (rev 5223)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-09-26 16:54:16 UTC (rev 5224)
@@ -517,6 +517,8 @@
<Compile Include="NHSpecificTest\NH2331\Person.cs" />
<Compile Include="NHSpecificTest\NH2344\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2344\Model.cs" />
+ <Compile Include="PolymorphicGetAndLoad\Domain.cs" />
+ <Compile Include="PolymorphicGetAndLoad\PolymorphicGetAndLoadTest.cs" />
<Compile Include="TypesTest\CharClass.cs" />
<Compile Include="TypesTest\CharClassFixture.cs" />
<Compile Include="TypesTest\DateTimeClass.cs" />
@@ -2312,6 +2314,7 @@
<EmbeddedResource Include="CollectionTest\NullableValueTypeElementMapFixture.hbm.xml" />
<EmbeddedResource Include="DriverTest\EntityForMs2008.hbm.xml" />
<Content Include="DynamicEntity\package.html" />
+ <EmbeddedResource Include="PolymorphicGetAndLoad\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2331\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2324\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2344\Mappings.hbm.xml" />
@@ -2655,7 +2658,6 @@
<EmbeddedResource Include="DynamicEntity\Tuplizer\Customer.hbm.xml" />
</ItemGroup>
<ItemGroup>
- <Folder Include="NHSpecificTest\NH2202" />
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
Added: trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Domain.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Domain.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Domain.cs 2010-09-26 16:54:16 UTC (rev 5224)
@@ -0,0 +1,41 @@
+namespace NHibernate.Test.PolymorphicGetAndLoad
+{
+ public class A: INamed
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+
+ public interface IOccuped
+ {
+ string Occupation { get; set; }
+ }
+
+ public class B: A, IOccuped
+ {
+ public virtual string Occupation { get; set; }
+ }
+
+ public interface INamed
+ {
+ string Name { get; set; }
+ }
+
+ public class GraphA : IMultiGraphNamed
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+
+ public class GraphB : IMultiGraphNamed
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+
+ public interface IMultiGraphNamed
+ {
+ string Name { get; set; }
+ }
+
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/Mappings.hbm.xml 2010-09-26 16:54:16 UTC (rev 5224)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping
+ xmlns="urn:nhibernate-mapping-2.2"
+ assembly="NHibernate.Test"
+ namespace="NHibernate.Test.PolymorphicGetAndLoad">
+
+ <class name="A">
+ <id name="Id">
+ <generator class="hilo" />
+ </id>
+ <property name="Name"/>
+ <joined-subclass name="B">
+ <key column="AId"/>
+ <property name="Occupation"/>
+ </joined-subclass>
+ </class>
+
+ <class name="GraphA">
+ <id name="Id">
+ <generator class="hilo" />
+ </id>
+ <property name="Name"/>
+ </class>
+
+ <class name="GraphB">
+ <id name="Id">
+ <generator class="hilo" />
+ </id>
+ <property name="Name"/>
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/PolymorphicGetAndLoadTest.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/PolymorphicGetAndLoadTest.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/PolymorphicGetAndLoad/PolymorphicGetAndLoadTest.cs 2010-09-26 16:54:16 UTC (rev 5224)
@@ -0,0 +1,260 @@
+using System;
+using System.Collections;
+using NHibernate.Engine;
+using NHibernate.Proxy;
+using NUnit.Framework;
+using SharpTestsEx;
+
+namespace NHibernate.Test.PolymorphicGetAndLoad
+{
+ public class PolymorphicGetAndLoadTest: TestCase
+ {
+ protected override string MappingsAssembly
+ {
+ get { return "NHibernate.Test"; }
+ }
+
+ protected override IList Mappings
+ {
+ get { return new[] { "PolymorphicGetAndLoad.Mappings.hbm.xml" }; }
+ }
+
+ public class ScenarioWithA : IDisposable
+ {
+ private readonly ISessionFactory factory;
+ private readonly A a;
+
+ public ScenarioWithA(ISessionFactory factory)
+ {
+ this.factory = factory;
+ a = new A { Name = "Patrick" };
+ using (var s = factory.OpenSession())
+ {
+ s.Save(a);
+ s.Flush();
+ }
+ }
+
+ public A A
+ {
+ get { return a; }
+ }
+
+ public void Dispose()
+ {
+ using (var s = factory.OpenSession())
+ {
+ s.Delete(a);
+ s.Flush();
+ }
+ }
+ }
+
+ public class ScenarioWithB : IDisposable
+ {
+ private readonly ISessionFactory factory;
+ private readonly B b;
+
+ public ScenarioWithB(ISessionFactory factory)
+ {
+ this.factory = factory;
+ b = new B { Name = "Patrick", Occupation = "hincha pelotas (en el buen sentido), but good candidate to be committer."};
+ using (var s = factory.OpenSession())
+ {
+ s.Save(b);
+ s.Flush();
+ }
+ }
+
+ public B B
+ {
+ get { return b; }
+ }
+
+ public void Dispose()
+ {
+ using (var s = factory.OpenSession())
+ {
+ s.Delete(b);
+ s.Flush();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenSaveDeleteBaseClassCastedToInterfaceThenNotThrows()
+ {
+ INamed a = new A { Name = "Patrick" };
+ Executing.This(() =>
+ {
+ using (var s = OpenSession())
+ {
+ s.Save(a);
+ s.Flush();
+ }
+ }).Should().NotThrow();
+
+ Executing.This(() =>
+ {
+ using (var s = OpenSession())
+ {
+ s.Delete(a);
+ s.Flush();
+ }
+ }).Should().NotThrow();
+
+ }
+
+ [Test]
+ public void WhenLoadBaseClassUsingInterfaceThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithA(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ s.Executing(session => session.Load<INamed>(scenario.A.Id)).NotThrows();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenGetBaseClassUsingInterfaceThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithA(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ s.Executing(session => session.Get<INamed>(scenario.A.Id)).NotThrows();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenLoadInheritedClassUsingInterfaceThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithB(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ Executing.This(()=> s.Load<INamed>(scenario.B.Id) ).Should().NotThrow();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenLoadInheritedClassUsingInterfaceThenShouldAllowNarrowingProxy()
+ {
+ using (var scenario = new ScenarioWithB(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ INamed loadedEntity = null;
+ Executing.This(() => loadedEntity = s.Load<INamed>(scenario.B.Id)).Should().NotThrow();
+ NHibernateProxyHelper.GetClassWithoutInitializingProxy(loadedEntity).Should().Be(typeof(A));
+
+ var narrowedProxy = s.Load<B>(scenario.B.Id);
+
+ NHibernateProxyHelper.GetClassWithoutInitializingProxy(narrowedProxy).Should().Be(typeof(B));
+
+ var firstLoadedImpl = ((INHibernateProxy)loadedEntity).HibernateLazyInitializer.GetImplementation((ISessionImplementor)s);
+ var secondLoadedImpl = ((INHibernateProxy)narrowedProxy).HibernateLazyInitializer.GetImplementation((ISessionImplementor)s);
+ firstLoadedImpl.Should().Be.SameInstanceAs(secondLoadedImpl);
+ }
+ }
+ }
+
+ [Test]
+ public void WhenLoadInterfaceThenShouldAllowNarrowingProxy()
+ {
+ using (var scenario = new ScenarioWithB(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ INamed loadedEntity = null;
+ Executing.This(() => loadedEntity = s.Load<INamed>(scenario.B.Id)).Should().NotThrow();
+ NHibernateProxyHelper.GetClassWithoutInitializingProxy(loadedEntity).Should().Be(typeof(A));
+
+ var narrowedProxy = s.Load<IOccuped>(scenario.B.Id);
+
+ NHibernateProxyHelper.GetClassWithoutInitializingProxy(narrowedProxy).Should().Be(typeof(B));
+
+ var firstLoadedImpl = ((INHibernateProxy)loadedEntity).HibernateLazyInitializer.GetImplementation((ISessionImplementor)s);
+ var secondLoadedImpl = ((INHibernateProxy)narrowedProxy).HibernateLazyInitializer.GetImplementation((ISessionImplementor)s);
+ firstLoadedImpl.Should().Be.SameInstanceAs(secondLoadedImpl);
+ }
+ }
+ }
+
+ [Test]
+ public void WhenGetInheritedClassUsingInterfaceThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithB(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ INamed loadedEntity = null;
+ Executing.This(() => loadedEntity = s.Get<INamed>(scenario.B.Id)).Should().NotThrow();
+ loadedEntity.Should().Be.OfType<B>();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenLoadClassUsingInterfaceOfMultippleHierarchyThenThrows()
+ {
+ using (var s = OpenSession())
+ {
+ Executing.This(() => s.Load<IMultiGraphNamed>(1))
+ .Should().Throw<HibernateException>()
+ .And.ValueOf.Message.Should()
+ .Contain("Ambiguous")
+ .And.Contain("GraphA")
+ .And.Contain("GraphB")
+ .And.Contain("IMultiGraphNamed");
+ }
+ }
+
+ [Test]
+ public void WhenGetClassUsingInterfaceOfMultippleHierarchyThenThrows()
+ {
+ using (var s = OpenSession())
+ {
+ Executing.This(() => s.Get<IMultiGraphNamed>(1))
+ .Should().Throw<HibernateException>()
+ .And.ValueOf.Message.Should()
+ .Contain("Ambiguous")
+ .And.Contain("GraphA")
+ .And.Contain("GraphB")
+ .And.Contain("IMultiGraphNamed");
+ }
+ }
+
+ [Test]
+ public void WhenGetBaseClassUsingInterfaceFromSessionCacheThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithA(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ var id = scenario.A.Id;
+ s.Get<A>(id);
+ s.Executing(session => session.Get<INamed>(id)).NotThrows();
+ }
+ }
+ }
+
+ [Test]
+ public void WhenGetInheritedClassUsingInterfaceFromSessionCacheThenNotThrows()
+ {
+ using (var scenario = new ScenarioWithB(Sfi))
+ {
+ using (var s = OpenSession())
+ {
+ var id = scenario.B.Id;
+ s.Get<B>(id);
+ s.Executing(session => session.Get<INamed>(id)).NotThrows();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|