|
From: <fab...@us...> - 2010-12-10 16:47:17
|
Revision: 5302
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5302&view=rev
Author: fabiomaulo
Date: 2010-12-10 16:47:11 +0000 (Fri, 10 Dec 2010)
Log Message:
-----------
Fix NH-2410 (Port <properties> from Hibernate) thanks to Roger Kratz
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs
trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs
trunk/nhibernate/src/NHibernate/Mapping/PersistentClass.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperties.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Mappings.hbm.xml
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Model.cs
Added: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperties.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperties.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperties.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Serialization;
+
+namespace NHibernate.Cfg.MappingSchema
+{
+ public partial class HbmProperties : AbstractDecoratable, IEntityPropertyMapping, IComponentMapping
+ {
+ #region Implementation of IEntityPropertyMapping
+
+ public bool IsLazyProperty
+ {
+ get { return false; }
+ }
+
+ public string Class
+ {
+ get { return null; }
+ }
+
+ public HbmParent Parent
+ {
+ get { return null; }
+ }
+
+ public string EmbeddedNode
+ {
+ get { return node; }
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public string Access
+ {
+ get { return "embedded"; }
+ }
+
+ public bool OptimisticLock
+ {
+ get { return optimisticlock; }
+ }
+
+ #endregion
+
+ #region Implementation of IPropertiesContainerMapping
+
+ [XmlIgnore]
+ public IEnumerable<IEntityPropertyMapping> Properties
+ {
+ get { return Items != null ? Items.Cast<IEntityPropertyMapping>() : new IEntityPropertyMapping[0]; }
+ }
+
+ #endregion
+
+ #region Overrides of AbstractDecoratable
+
+ protected override HbmMeta[] Metadatas
+ {
+ get { return new HbmMeta[0]; }
+ }
+
+ #endregion
+ }
+}
Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs 2010-12-10 14:23:49 UTC (rev 5301)
+++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -286,6 +286,7 @@
model.IsEmbedded = false;
model.IsDynamic = true;
}
+
else if (reflectedClass != null)
{
model.ComponentClass = reflectedClass;
@@ -294,8 +295,15 @@
else
{
// an "embedded" component (ids only)
- model.ComponentClass = model.Owner.MappedClass;
model.IsEmbedded = true;
+ if (model.Owner.HasPocoRepresentation)
+ {
+ model.ComponentClass = model.Owner.MappedClass;
+ }
+ else
+ {
+ model.IsDynamic = true;
+ }
}
string nodeName = !string.IsNullOrEmpty(componentMapping.EmbeddedNode)
Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-12-10 14:23:49 UTC (rev 5301)
+++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -83,6 +83,7 @@
HbmNestedCompositeElement nestedCompositeElementMapping;
HbmKeyProperty keyPropertyMapping;
HbmKeyManyToOne keyManyToOneMapping;
+ HbmProperties propertiesMapping;
if ((propertyMapping = entityPropertyMapping as HbmProperty) != null)
{
@@ -104,6 +105,14 @@
property = CreateProperty(collectionMapping, className, collection, inheritedMetas);
BindCollectionProperty(collectionMapping, property);
}
+ else if ((propertiesMapping = entityPropertyMapping as HbmProperties) != null)
+ {
+ var subpath = propertyName == null ? null : StringHelper.Qualify(propertyBasePath, propertyName);
+ var value = CreateNewComponent(table);
+ BindComponent(propertiesMapping, value, null, entityName, subpath, componetDefaultNullable, inheritedMetas);
+ property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas);
+ BindComponentProperty(propertiesMapping, property, value);
+ }
else if ((manyToOneMapping = entityPropertyMapping as HbmManyToOne) != null)
{
var value = new ManyToOne(table);
@@ -326,6 +335,16 @@
}
}
+ private void BindComponentProperty(HbmProperties propertiesMapping, Property property, Component model)
+ {
+ property.IsUpdateable = propertiesMapping.update;
+ property.IsInsertable = propertiesMapping.insert;
+ if (propertiesMapping.unique)
+ {
+ model.Owner.Table.CreateUniqueKey(model.ColumnIterator.OfType<Column>().ToList());
+ }
+ }
+
private void BindComponentProperty(HbmComponent componentMapping, Property property, Component model)
{
property.IsUpdateable = componentMapping.update;
Modified: trunk/nhibernate/src/NHibernate/Mapping/PersistentClass.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/PersistentClass.cs 2010-12-10 14:23:49 UTC (rev 5301)
+++ trunk/nhibernate/src/NHibernate/Mapping/PersistentClass.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -910,9 +910,10 @@
private Property GetProperty(string propertyName, IEnumerable<Property> iter)
{
- foreach (Property prop in iter)
+ var propName = StringHelper.Root(propertyName);
+ foreach (var prop in iter)
{
- if (prop.Name.Equals(StringHelper.Root(propertyName)))
+ if (prop.Name.Equals(propName))
{
return prop;
}
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-12-10 14:23:49 UTC (rev 5301)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-12-10 16:47:11 UTC (rev 5302)
@@ -530,6 +530,7 @@
<Compile Include="Cfg\MappingSchema\HbmOneToMany.cs" />
<Compile Include="Cfg\MappingSchema\HbmOneToOne.cs" />
<Compile Include="Cfg\MappingSchema\HbmPrimitiveArray.cs" />
+ <Compile Include="Cfg\MappingSchema\HbmProperties.cs" />
<Compile Include="Cfg\MappingSchema\HbmProperty.cs" />
<Compile Include="Cfg\MappingSchema\HbmSet.cs" />
<Compile Include="Cfg\MappingSchema\HbmSubclass.cs" />
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/CompositePropertyRefTest.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -0,0 +1,142 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.Properties
+{
+ [TestFixture]
+ public class CompositePropertyRefTest : BugTestCase
+ {
+ private long p_id;
+ private long p2_id;
+
+ protected override void OnSetUp()
+ {
+ using (var s = OpenSession())
+ {
+ using (var tx = s.BeginTransaction())
+ {
+ var p = new Person { Name = "Steve", UserId = "steve" };
+ var a = new Address { Addr = "Texas", Country = "USA", Person = p };
+ var p2 = new Person { Name = "Max", UserId = "max" };
+ var act = new Account { Type = Convert.ToChar("c"), User = p2 };
+ p2.Accounts.Add(act);
+ p_id = (long)s.Save(p);
+ s.Save(a);
+ p2_id = (long)s.Save(p2);
+ s.Save(act);
+ tx.Commit();
+ }
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var s = OpenSession())
+ {
+ using (var tx = s.BeginTransaction())
+ {
+ s.Delete("from Account");
+ s.Delete("from Address");
+ s.Delete("from Person");
+ tx.Commit();
+ }
+ }
+ }
+
+ [Test]
+ public void MappingOuterJoin()
+ {
+ using(var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var p = s.Get<Person>(p_id); //get address reference by outer join
+ var p2 = s.Get<Person>(p2_id); //get null address reference by outer join
+ Assert.IsNull(p2.Address);
+ Assert.IsNotNull(p.Address);
+ var l = s.CreateQuery("from Person").List(); //pull address references for cache
+ Assert.AreEqual(l.Count, 2);
+ Assert.IsTrue(l.Contains(p) && l.Contains(p2));
+ }
+ }
+ }
+
+ [Test]
+ public void AddressBySequentialSelect()
+ {
+ using (var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var l = s.CreateQuery("from Person p order by p.Name").List<Person>();
+ Assert.AreEqual(l.Count, 2);
+ Assert.IsNull(l[0].Address);
+ Assert.IsNotNull(l[1].Address);
+ }
+ }
+ }
+
+ [Test]
+ public void AddressOuterJoin()
+ {
+ using (var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var l = s.CreateQuery("from Person p left join fetch p.Address a order by a.Country").List<Person>();
+ Assert.AreEqual(l.Count, 2);
+ if (l[0].Name.Equals("Max"))
+ {
+ Assert.IsNull(l[0].Address);
+ Assert.IsNotNull(l[1].Address);
+ }
+ else
+ {
+ Assert.IsNull(l[1].Address);
+ Assert.IsNotNull(l[0].Address);
+ }
+ }
+ }
+ }
+
+ [Test]
+ public void AccountsOuterJoin()
+ {
+ using (var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var l = s.CreateQuery("from Person p left join p.Accounts").List();
+ for (var i = 0; i < 2; i++)
+ {
+ var row = (object[])l[i];
+ var px = (Person)row[0];
+ var accounts = px.Accounts;
+ Assert.IsFalse(NHibernateUtil.IsInitialized(accounts));
+ Assert.IsTrue(px.Accounts.Count > 0 || row[1] == null);
+ }
+ }
+ }
+ }
+
+ [Test]
+ public void AccountsOuterJoinVerifyInitialization()
+ {
+ using (var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var l = s.CreateQuery("from Person p left join fetch p.Accounts a order by p.Name").List<Person>();
+ var p0 = l[0];
+ Assert.IsTrue(NHibernateUtil.IsInitialized(p0.Accounts));
+ Assert.AreEqual(p0.Accounts.Count, 1);
+ Assert.AreSame(p0.Accounts.First().User, p0);
+ var p1 = l[1];
+ Assert.IsTrue(NHibernateUtil.IsInitialized(p1.Accounts));
+ Assert.AreEqual(p1.Accounts.Count, 0);
+ }
+ }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/DynamicEntityTest.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -0,0 +1,56 @@
+using System.Collections;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.Properties
+{
+ [TestFixture]
+ public class DynamicEntityTest : BugTestCase
+ {
+ protected override void OnSetUp()
+ {
+ using (var s = OpenSession())
+ {
+ using (var tx = s.BeginTransaction())
+ {
+ var props = new Dictionary<string, object>();
+ props["Foo"] = "Sweden";
+ props["Bar"] = "IsCold";
+ s.Save("DynamicEntity", new Dictionary<string, object>
+ {
+ {"SomeProps", props},
+ });
+ tx.Commit();
+ }
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var s = OpenSession())
+ {
+ using (var tx = s.BeginTransaction())
+ {
+ s.Delete("from DynamicEntity");
+ tx.Commit();
+ }
+ }
+ }
+
+ [Test]
+ public void CanFetchByProperty()
+ {
+ using (var s = OpenSession())
+ {
+ using (s.BeginTransaction())
+ {
+ var l = s.CreateQuery("from DynamicEntity de where de.SomeProps.Foo=:fooParam")
+ .SetString("fooParam", "Sweden").List();
+ Assert.AreEqual(1, l.Count);
+ var props = ((IDictionary)l[0])["SomeProps"];
+ Assert.AreEqual("IsCold", ((IDictionary)props)["Bar"]);
+ }
+ }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Mappings.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Mappings.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Mappings.hbm.xml 2010-12-10 16:47:11 UTC (rev 5302)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
+ namespace="NHibernate.Test.NHSpecificTest.Properties"
+ assembly="NHibernate.Test">
+
+ <class entity-name="DynamicEntity">
+ <id name="Id" type="Int32">
+ <generator class="hilo"/>
+
+ </id>
+ <properties name="SomeProps">
+ <property name="Foo" type="string"/>
+ <property name="Bar" type="string"/>
+ </properties>
+ </class>
+
+ <class name="Person">
+ <id name="Id">
+ <generator class="hilo"/>
+ </id>
+ <property name="Name" length="100"/>
+ <one-to-one name="Address" property-ref="Person" cascade="all" fetch="join"/>
+ <set name="Accounts" inverse="true">
+ <key property-ref="UserIdAndDeleted">
+ <column name="userId"/>
+ <column name="userDeleted"/>
+ </key>
+ <one-to-many class="Account"/>
+ </set>
+ <properties name="UserIdAndDeleted" update="false" unique="true">
+ <property name="UserId" length="8"/>
+ <property name="Deleted"/>
+ </properties>
+ </class>
+
+ <class name="Address">
+ <id name="Id">
+ <generator class="hilo"/>
+
+ </id>
+ <property name="Addr" length="300"/>
+ <property name="Zip" length="5"/>
+ <property name="Country" length="25"/>
+ <many-to-one name="Person" unique="true" not-null="true"/>
+ </class>
+
+ <class name="Account" table="`Account`">
+ <id name="AccountId" length="32">
+ <generator class="uuid.hex"/>
+ </id>
+ <many-to-one name="User" property-ref="UserIdAndDeleted">
+ <column name="userId"/>
+ <column name="userDeleted"/>
+ </many-to-one>
+ <property name="Type" column="`type`" not-null="true"/>
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Model.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Model.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Properties/Model.cs 2010-12-10 16:47:11 UTC (rev 5302)
@@ -0,0 +1,42 @@
+using Iesi.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.Properties
+{
+ public class Person
+ {
+ public virtual long Id { get; set; }
+ public virtual string Name { get; set; }
+ public virtual Address Address { get; set; }
+ public virtual string UserId { get; set; }
+ public virtual bool Deleted { get; set; }
+ public virtual ISet<Account> Accounts { get; set; }
+
+ public Person()
+ {
+ Accounts = new HashedSet<Account>();
+ }
+ }
+
+ public class Address
+ {
+ public virtual long Id { get; set; }
+ public virtual string Addr { get; set; }
+ public virtual string Zip { get; set; }
+ public virtual string Country { get; set; }
+ public virtual Person Person { get; set; }
+ }
+
+ public class Account
+ {
+ public virtual string AccountId { get; set; }
+ public virtual Person User { get; set; }
+ public virtual char Type { get; set; }
+ }
+
+ public class DynamicEntity
+ {
+ public virtual long Id { get; set; }
+ public virtual string Foo { get; set; }
+ public virtual string Bar { get; set; }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-12-10 14:23:49 UTC (rev 5301)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-12-10 16:47:11 UTC (rev 5302)
@@ -540,6 +540,9 @@
<Compile Include="NHSpecificTest\NH2420\MyTable.cs" />
<Compile Include="NHSpecificTest\NH2441\Fixture.cs" />
<Compile Include="NHSpecificTest\NH2441\Model.cs" />
+ <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" />
+ <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" />
+ <Compile Include="NHSpecificTest\Properties\Model.cs" />
<Compile Include="PolymorphicGetAndLoad\Domain.cs" />
<Compile Include="PolymorphicGetAndLoad\PolymorphicGetAndLoadTest.cs" />
<Compile Include="TypesTest\CharClass.cs" />
@@ -2348,6 +2351,7 @@
<EmbeddedResource Include="CollectionTest\NullableValueTypeElementMapFixture.hbm.xml" />
<EmbeddedResource Include="DriverTest\EntityForMs2008.hbm.xml" />
<Content Include="DynamicEntity\package.html" />
+ <EmbeddedResource Include="NHSpecificTest\Properties\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2378\Mappings.hbm.xml" />
<EmbeddedResource Include="TypesTest\XDocClass.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH2374\Mappings.hbm.xml" />
@@ -2685,8 +2689,6 @@
<EmbeddedResource Include="DynamicEntity\Tuplizer\Customer.hbm.xml" />
</ItemGroup>
<ItemGroup>
- <Folder Include="NHSpecificTest\NH2420" />
- <Folder Include="NHSpecificTest\NH2441" />
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|