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. |