From: <jul...@us...> - 2011-01-24 16:17:47
|
Revision: 5368 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5368&view=rev Author: julian-maughan Date: 2011-01-24 16:17:41 +0000 (Mon, 24 Jan 2011) Log Message: ----------- Fixed minor deficiency whereby the value of a 'length' attribute on the property mapping of a serialiable type is ignored [ref. NH-2484]. Thanks to Ivan Zlatev. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Mapping/SimpleValue.cs trunk/nhibernate/src/NHibernate/Type/SerializableType.cs trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Model.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/food-photo.jpg Modified: trunk/nhibernate/src/NHibernate/Mapping/SimpleValue.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/SimpleValue.cs 2011-01-24 15:51:51 UTC (rev 5367) +++ trunk/nhibernate/src/NHibernate/Mapping/SimpleValue.cs 2011-01-24 16:17:41 UTC (rev 5368) @@ -247,18 +247,21 @@ { // NH different behavior // If the mapping has a type as "Double(10,5)" our SqlType will be created with all information - // including the rigth SqlType specification but when the length/presion/scale was specified - // trough attributes the SqlType is wrong (does not include length/presion/scale specification) + // including the right SqlType specification, but when the length/precision/scale was specified + // through attributes the SqlType is wrong (does not include length/precision/scale specification) IType result = null; if (ColumnSpan == 1 && !columns[0].IsFormula) { - var col = (Column) columns[0]; - if(col.IsLengthDefined()) + var col = (Column)columns[0]; + if (col.IsLengthDefined()) { result = TypeFactory.BuiltInType(typeName, col.Length); + + if (result == null) + result = TypeFactory.HeuristicType(typeName, typeParameters, col.Length); } - else if(col.IsPrecisionDefined()) + else if (col.IsPrecisionDefined()) { result = TypeFactory.BuiltInType(typeName, Convert.ToByte(col.Precision), Convert.ToByte(col.Scale)); } Modified: trunk/nhibernate/src/NHibernate/Type/SerializableType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/SerializableType.cs 2011-01-24 15:51:51 UTC (rev 5367) +++ trunk/nhibernate/src/NHibernate/Type/SerializableType.cs 2011-01-24 16:17:41 UTC (rev 5368) @@ -14,8 +14,9 @@ /// </summary> /// <remarks> /// <para> - /// The SerializableType should be used when you know that Bytes are - /// not going to be greater than 8,000. + /// For performance reasons, the SerializableType should be used when you know that Bytes are + /// not going to be greater than 8,000. Implementing a custom type is recommended for larger + /// types. /// </para> /// <para> /// The base class is <see cref="MutableType"/> because the data is stored in Modified: trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-01-24 15:51:51 UTC (rev 5367) +++ trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-01-24 16:17:41 UTC (rev 5368) @@ -21,7 +21,7 @@ /// <remarks> /// Applications should use static methods and constants on NHibernate.NHibernateUtil if the default /// IType is good enough. For example, the TypeFactory should only be used when the String needs - /// to have a length of 300 instead of 255. At this point NHibernate.String does not get you the + /// to have a length of 300 instead of 255. At this point NHibernateUtil.String does not get you the /// correct IType. Instead use TypeFactory.GetString(300) and keep a local variable that holds /// a reference to the IType. /// </remarks> @@ -33,8 +33,8 @@ Length, PrecisionScale } + private static readonly string[] EmptyAliases= new string[0]; - private static readonly char[] PrecisionScaleSplit = new[] { '(', ')', ',' }; private static readonly char[] LengthSplit = new[] { '(', ')' }; private static readonly TypeFactory Instance; @@ -446,14 +446,25 @@ } /// <summary> - /// Uses heuristics to deduce a NHibernate type given a string naming the - /// type. + /// Uses heuristics to deduce a NHibernate type given a string naming the type. /// </summary> /// <param name="typeName">the type name</param> /// <param name="parameters">parameters for the type</param> /// <returns>An instance of <c>NHibernate.Type.IType</c></returns> public static IType HeuristicType(string typeName, IDictionary<string, string> parameters) { + return HeuristicType(typeName, parameters, null); + } + + /// <summary> + /// Uses heuristics to deduce a NHibernate type given a string naming the type. + /// </summary> + /// <param name="typeName">the type name</param> + /// <param name="parameters">parameters for the type</param> + /// <param name="length">optionally, the size of the type</param> + /// <returns></returns> + public static IType HeuristicType(string typeName, IDictionary<string, string> parameters, int? length) + { IType type = Basic(typeName); if (type == null) @@ -518,6 +529,10 @@ { type = GetSerializableType(typeClass, Int32.Parse(parsedTypeName[1])); } + else if (length != null) + { + type = GetSerializableType(typeClass, length.Value); + } else { type = GetSerializableType(typeClass); Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Fixture.cs 2011-01-24 16:17:41 UTC (rev 5368) @@ -0,0 +1,79 @@ +using System; +using System.Drawing; +using NUnit.Framework; +using NHibernate.Type; +using NHibernate.SqlTypes; + +namespace NHibernate.Test.NHSpecificTest.NH2484 +{ +[TestFixture] + public class Fixture : BugTestCase + { + protected override bool AppliesTo(NHibernate.Dialect.Dialect dialect) + { + return (dialect is Dialect.MsSql2008Dialect); + } + + [Test] + public void TestPersistenceOfClassWithUnknownSerializableType() + { + var stream = this.GetType().Assembly.GetManifestResourceStream("NHibernate.Test.NHSpecificTest.NH2484.food-photo.jpg"); + var image = Bitmap.FromStream(stream); + + var model = new ClassWithImage() { Image = image }; + var imageSize = model.Image.Size; + int id = -1; + + using (ISession session = OpenSession()) + { + session.SaveOrUpdate(model); + session.Flush(); + id = model.Id; + Assert.That(id, Is.GreaterThan(-1)); + } + using (ISession session = OpenSession()) + { + model = session.Get<ClassWithImage>(id); + Assert.That(model.Image.Size, Is.EqualTo(imageSize)); // Ensure type is not truncated + } + using (ISession session = OpenSession()) + { + session.CreateQuery("delete from ClassWithImage").ExecuteUpdate(); + session.Flush(); + } + + stream.Dispose(); + } + + [Test] + public void TestPersistenceOfClassWithSerializableType() + { + var stream = this.GetType().Assembly.GetManifestResourceStream("NHibernate.Test.NHSpecificTest.NH2484.food-photo.jpg"); + var image = Bitmap.FromStream(stream); + + var model = new ClassWithSerializableType() { Image = image }; + var imageSize = ((Image)model.Image).Size; + int id = -1; + + using (ISession session = OpenSession()) + { + session.SaveOrUpdate(model); + session.Flush(); + id = model.Id; + Assert.That(id, Is.GreaterThan(-1)); + } + using (ISession session = OpenSession()) + { + model = session.Get<ClassWithSerializableType>(id); + Assert.That(((Image)model.Image).Size, Is.EqualTo(imageSize)); // Ensure type is not truncated + } + using (ISession session = OpenSession()) + { + session.CreateQuery("delete from ClassWithSerializableType").ExecuteUpdate(); + session.Flush(); + } + + stream.Dispose(); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Mappings.hbm.xml 2011-01-24 16:17:41 UTC (rev 5368) @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping + xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2484"> + + <class name="ClassWithImage"> + + <id name="Id"> + <generator class="native" /> + </id> + + <property name="Image" type="System.Drawing.Image, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <column name="Image" length="10000" not-null="false" /> + </property> + + </class> + + <class name="ClassWithSerializableType"> + + <id name="Id"> + <generator class="native" /> + </id> + + <property name="Image" type="Serializable(10000)"> + <column name="Image" not-null="false" /> + </property> + + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/Model.cs 2011-01-24 16:17:41 UTC (rev 5368) @@ -0,0 +1,17 @@ +using System; +using System.Runtime.Serialization; + +namespace NHibernate.Test.NHSpecificTest.NH2484 +{ + public class ClassWithImage + { + public virtual int Id { get; set; } + public virtual System.Drawing.Image Image { get; set; } + } + + public class ClassWithSerializableType + { + public virtual int Id { get; set; } + public virtual ISerializable Image { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/food-photo.jpg =================================================================== (Binary files differ) Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2484/food-photo.jpg ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-24 15:51:51 UTC (rev 5367) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-24 16:17:41 UTC (rev 5368) @@ -91,6 +91,7 @@ </Reference> <Reference Include="System.Data" /> <Reference Include="System.Data.OracleClient" /> + <Reference Include="System.Drawing" /> <Reference Include="System.Linq.Dynamic, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\..\lib\net\3.5\System.Linq.Dynamic.dll</HintPath> @@ -608,6 +609,8 @@ <Compile Include="NHSpecificTest\NH2470\Class1Class2Tests.cs" /> <Compile Include="NHSpecificTest\NH2470\DomainObject.cs" /> <Compile Include="NHSpecificTest\NH2470\DTO.cs" /> + <Compile Include="NHSpecificTest\NH2484\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2484\Model.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> @@ -1912,6 +1915,8 @@ <EmbeddedResource Include="NHSpecificTest\NH2409\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2420\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2441\Mappings.hbm.xml" /> + <EmbeddedResource Include="NHSpecificTest\NH2484\food-photo.jpg" /> + <EmbeddedResource Include="NHSpecificTest\NH2484\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\NHibernate.ByteCode.Castle\NHibernate.ByteCode.Castle.csproj"> @@ -2779,6 +2784,7 @@ <EmbeddedResource Include="DynamicEntity\Tuplizer\Customer.hbm.xml" /> </ItemGroup> <ItemGroup> + <Folder Include="NHSpecificTest\NH2484" /> <Folder Include="Properties\" /> </ItemGroup> <ItemGroup> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-01-29 18:06:47
|
Revision: 5372 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5372&view=rev Author: patearl Date: 2011-01-29 18:06:40 +0000 (Sat, 29 Jan 2011) Log Message: ----------- Linq: Handle ConvertChecked when generating HQL. (NH-2507, thanks Sue Hackett.) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Animal.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-01-26 15:02:50 UTC (rev 5371) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-01-29 18:06:40 UTC (rev 5372) @@ -330,6 +330,7 @@ case ExpressionType.Not: return _hqlTreeBuilder.BooleanNot(VisitExpression(expression.Operand).AsBooleanExpression()); case ExpressionType.Convert: + case ExpressionType.ConvertChecked: return VisitExpression(expression.Operand); } Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Animal.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Animal.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Animal.cs 2011-01-29 18:06:40 UTC (rev 5372) @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2507 +{ + public enum Sex + { + Undefined = 0, + Male = 1, + Female = 2 + } + + public class Animal + { + public virtual int Id { get; set; } + public virtual string Description { get; set; } + public virtual double BodyWeight { get; set; } + public virtual Sex Sex { get; set; } + public virtual Animal Mother { get; set; } + public virtual Animal Father { get; set; } + public virtual IList<Animal> Children { get; set; } + public virtual string SerialNumber { get; set; } + } + + public abstract class Reptile : Animal + { + public virtual double BodyTemperature { get; set; } + } + + public class Lizard : Reptile { } + + public abstract class Mammal : Animal + { + public virtual bool Pregnant { get; set; } + public virtual DateTime? BirthDate { get; set; } + } + + public class Dog : Mammal { } + + public class Cat : Mammal { } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Fixture.cs 2011-01-29 18:06:40 UTC (rev 5372) @@ -0,0 +1,133 @@ +using System; +using System.Linq; +using NHibernate.Dialect; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2507 +{ + /// <summary> + /// Used for testing LINQ queries in NHibernate that compare enumeration values. + /// </summary> + [TestFixture] + public class Fixture : BugTestCase + { + #region BugTestCase Overrides + + protected override void OnSetUp() + { + base.OnSetUp(); + using (ISession session = this.OpenSession()) + { + Animal animal = new Animal() + { + Id = 1, BodyWeight = 2, Sex = Sex.Undefined, Description = "Animal", + SerialNumber = "111" + }; + Lizard lizard = new Lizard() + { + Id = 2, + BodyTemperature = 98, + BodyWeight = 10, + Sex = Sex.Male, + Description = "Lizard", + SerialNumber = "222", + Mother = animal + }; + Dog momDog = new Dog() + { + BirthDate = new DateTime(2007, 01, 01), + BodyWeight = 65, + Sex = Sex.Female, + Description = "MyDogMom", + Pregnant = false, + SerialNumber = "333" + }; + Dog dadDog = new Dog() + { + BirthDate = new DateTime(2007, 02, 02), + BodyWeight = 75, + Sex = Sex.Male, + Description = "MyDogDad", + Pregnant = false, + SerialNumber = "444" + }; + Dog puppy = new Dog() + { + BirthDate = new DateTime(2010, 01, 01), + BodyWeight = 50, + Sex = Sex.Male, + Description = "Puppy", + Pregnant = false, + Father = dadDog, + Mother = momDog, + SerialNumber = "555" + }; + Cat cat = new Cat() + { + BirthDate = new DateTime(2007, 03, 03), + BodyWeight = 10, + Sex = Sex.Female, + Description = "MyCat", + Pregnant = true, + SerialNumber = "777" + }; + + session.Save(animal); + session.Save(lizard); + session.Save(momDog); + session.Save(dadDog); + session.Save(puppy); + session.Save(cat); + session.Flush(); + } + } + + protected override void OnTearDown() + { + base.OnTearDown(); + using (ISession session = this.OpenSession()) + { + const string hql = "from System.Object"; + session.Delete(hql); + session.Flush(); + } + } + + #endregion BugTestCase Overrides + + /// <summary> + /// Test LINQ query that compares enumeration values while simulating projects with Advanced Build property + /// value for "Check for arithmetic overflow/underflow" as <b>checked</b>. + /// </summary> + [Test] + public void QueryEnumerationWithCheckedArithmeticOverflowTest() + { + using (ISession session = this.OpenSession()) + { + checked + { + var query = session.Query<Animal>().Where(item => item.Sex == Sex.Undefined).ToList(); + Assert.AreEqual(1, query.Count); + } + } + } + + /// <summary> + /// Test LINQ query that compares enumeration values while simulating projects with Advanced Build property + /// value for "Check for arithmetic overflow/underflow" as <b>unchecked</b>. + /// </summary> + [Test] + public void QueryEnumerationWithUncheckedArithmeticOverflowTest() + { + using (ISession session = this.OpenSession()) + { + unchecked + { + var query = session.Query<Animal>().Where(item => item.Sex == Sex.Undefined).ToList(); + Assert.AreEqual(1, query.Count); + } + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2507/Mappings.hbm.xml 2011-01-29 18:06:40 UTC (rev 5372) @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2507" + assembly="NHibernate.Test" + default-lazy="false"> + + <class name="Animal"> + <id name="Id"> + <generator class="native"/> + </id> + + <property name="Description"/> + <property name="BodyWeight" column="body_weight"/> + <property name="Sex" type="int" column="sex"/> + <many-to-one name="Mother" column="mother_id"/> + <many-to-one name="Father" column="father_id"/> + <property name="SerialNumber"/> + + <bag name="Children" lazy="true"> + <key column="ParentId" /> + <one-to-many class="Animal" /> + </bag> + + <joined-subclass name="Reptile"> + <key column="Animal"/> + <property name="BodyTemperature"/> + + <joined-subclass name="Lizard"> + <key column="Reptile"/> + </joined-subclass> + </joined-subclass> + + <joined-subclass name="Mammal"> + <key column="Animal"/> + <property name="Pregnant"/> + <property name="BirthDate" type="DateTime"/> + + <joined-subclass name="Dog"> + <key column="Mammal"/> + </joined-subclass> + + <joined-subclass name="Cat"> + <key column="Mammal"/> + </joined-subclass> + </joined-subclass> + </class> + +</hibernate-mapping> \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-26 15:02:50 UTC (rev 5371) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-29 18:06:40 UTC (rev 5372) @@ -611,6 +611,8 @@ <Compile Include="NHSpecificTest\NH2470\DTO.cs" /> <Compile Include="NHSpecificTest\NH2484\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2484\Model.cs" /> + <Compile Include="NHSpecificTest\NH2507\Animal.cs" /> + <Compile Include="NHSpecificTest\NH2507\Fixture.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> @@ -2405,6 +2407,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2507\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\EntityNameAndInheritance\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2467\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2459\Mappings.hbm.xml" /> @@ -2784,7 +2787,6 @@ <EmbeddedResource Include="DynamicEntity\Tuplizer\Customer.hbm.xml" /> </ItemGroup> <ItemGroup> - <Folder Include="NHSpecificTest\NH2484" /> <Folder Include="Properties\" /> </ItemGroup> <ItemGroup> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-02-05 22:43:54
|
Revision: 5374 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5374&view=rev Author: patearl Date: 2011-02-05 22:43:48 +0000 (Sat, 05 Feb 2011) Log Message: ----------- Linq: Support Cacheable before other operators. (NH-2502, thanks to Dean Ward for the fix.) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs trunk/nhibernate/src/NHibernate.Test/Linq/QueryCacheableTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs 2011-01-30 14:36:08 UTC (rev 5373) +++ trunk/nhibernate/src/NHibernate/Linq/ReWriters/ResultOperatorRewriter.cs 2011-02-05 22:43:48 UTC (rev 5374) @@ -63,6 +63,7 @@ { typeof(FetchRequestBase), typeof(OfTypeResultOperator), + typeof(CacheableResultOperator), }; private readonly List<ResultOperatorBase> resultOperators = new List<ResultOperatorBase>(); Modified: trunk/nhibernate/src/NHibernate.Test/Linq/QueryCacheableTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/QueryCacheableTests.cs 2011-01-30 14:36:08 UTC (rev 5373) +++ trunk/nhibernate/src/NHibernate.Test/Linq/QueryCacheableTests.cs 2011-02-05 22:43:48 UTC (rev 5374) @@ -85,5 +85,34 @@ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2)); Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1)); } + + [Test] + public void CacheableBeforeOtherClauses() + { + Sfi.Statistics.Clear(); + Sfi.QueryCache.Clear(); + + db.Customers.Cacheable().Where(c => c.ContactName != c.CompanyName).Take(1).ToList(); + db.Customers.Where(c => c.ContactName != c.CompanyName).Take(1).ToList(); + + Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2)); + Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1)); + Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(0)); + } + + [Test] + public void CacheableRegionBeforeOtherClauses() + { + Sfi.Statistics.Clear(); + Sfi.QueryCache.Clear(); + + db.Customers.Cacheable().CacheRegion("test").Where(c => c.ContactName != c.CompanyName).Take(1).ToList(); + db.Customers.Cacheable().CacheRegion("test").Where(c => c.ContactName != c.CompanyName).Take(1).ToList(); + db.Customers.Cacheable().CacheRegion("other").Where(c => c.ContactName != c.CompanyName).Take(1).ToList(); + + Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2)); + Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2)); + Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1)); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-02-19 13:55:00
|
Revision: 5384 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5384&view=rev Author: fabiomaulo Date: 2011-02-19 13:54:53 +0000 (Sat, 19 Feb 2011) Log Message: ----------- Apply patch of NH-2455 (thanks Michael DELVA) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs trunk/nhibernate/src/NHibernate/Event/Default/DefaultEvictEventListener.cs trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs trunk/nhibernate/src/NHibernate/Event/Default/DefaultSaveOrUpdateEventListener.cs trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/NHibernateUtil.cs trunk/nhibernate/src/NHibernate/Proxy/NHibernateProxyHelper.cs trunk/nhibernate/src/NHibernate/Type/CollectionType.cs trunk/nhibernate/src/NHibernate/Type/EntityType.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/ProxyInterface/CustomProxyFixture.cs trunk/nhibernate/src/NHibernate.ByteCode.LinFu/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs Modified: trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -38,5 +38,7 @@ IProxyValidator ProxyValidator { get; } bool IsInstrumented(System.Type entityClass); + + bool IsProxy(object entity); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -371,7 +371,7 @@ { string childEntityName = ((EntityType)type).GetAssociatedEntityName(session.Factory); - if (!IsInManagedState(child, session) && !(child is INHibernateProxy) && ForeignKeys.IsTransient(childEntityName, child, null, session)) + if (!IsInManagedState(child, session) && !(child.IsProxy()) && ForeignKeys.IsTransient(childEntityName, child, null, session)) { string parentEntiytName = persister.EntityName; string propertyName = persister.PropertyNames[propertyIndex]; Modified: trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -102,10 +102,11 @@ //if (obj == org.hibernate.intercept.LazyPropertyInitializer_Fields.UNFETCHED_PROPERTY) // return false; //this is kinda the best we can do... - INHibernateProxy proxy = obj as INHibernateProxy; - if (proxy != null) + if (obj.IsProxy()) { - // if its an uninitialized proxy it can't be transient + INHibernateProxy proxy = obj as INHibernateProxy; + + // if its an uninitialized proxy it can't be transient ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.GetImplementation(session) == null) { @@ -156,7 +157,7 @@ /// </remarks> public static bool IsNotTransient(string entityName, System.Object entity, bool? assumed, ISessionImplementor session) { - if (entity is INHibernateProxy) + if (entity.IsProxy()) return true; if (session.PersistenceContext.IsEntryFor(entity)) return true; Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -572,10 +572,11 @@ //{ // value = wrapper.Element; //} - var proxy = value as INHibernateProxy; - if (proxy != null) + if (value.IsProxy()) { - if (log.IsDebugEnabled) + var proxy = value as INHibernateProxy; + + if (log.IsDebugEnabled) { log.Debug("setting proxy identifier: " + id); } @@ -619,10 +620,11 @@ // maybeProxy = wrapper.Element; //} - INHibernateProxy proxy = maybeProxy as INHibernateProxy; - if (proxy != null) + if (maybeProxy.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; + INHibernateProxy proxy = maybeProxy as INHibernateProxy; + + ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.IsUninitialized) throw new PersistentObjectException("object was an uninitialized proxy for " + li.PersistentClass.FullName); @@ -647,10 +649,11 @@ //{ // maybeProxy = wrapper.Element; //} - var proxy = maybeProxy as INHibernateProxy; - if (proxy != null) + if (maybeProxy.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; + var proxy = maybeProxy as INHibernateProxy; + + ILazyInitializer li = proxy.HibernateLazyInitializer; ReassociateProxy(li, proxy); return li.GetImplementation(); //initialize + unwrap the object } Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultEvictEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultEvictEventListener.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultEvictEventListener.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -24,7 +24,7 @@ object obj = @event.Entity; IPersistenceContext persistenceContext = source.PersistenceContext; - if (obj is INHibernateProxy) + if (obj.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; object id = li.Identifier; Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -90,7 +90,7 @@ if (original != null) { object entity; - if (original is INHibernateProxy) + if (original.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)original).HibernateLazyInitializer; if (li.IsUninitialized) @@ -521,7 +521,7 @@ { object entityCopy = copyCache[entity]; - if (entityCopy is INHibernateProxy) + if (entityCopy.IsProxy()) entityCopy = ((INHibernateProxy)entityCopy).HibernateLazyInitializer.GetImplementation(); // NH-specific: Disregard entities that implement ILifecycle and manage their own state - they Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -38,7 +38,7 @@ object obj = @event.Entity; object entity; - if (obj is INHibernateProxy) + if (obj.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; if (li.IsUninitialized) Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultSaveOrUpdateEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultSaveOrUpdateEventListener.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultSaveOrUpdateEventListener.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -31,7 +31,7 @@ { //assign the requested id to the proxy, *before* //reassociating the proxy - if (obj is INHibernateProxy) + if (obj.IsProxy()) { ((INHibernateProxy)obj).HibernateLazyInitializer.Identifier = requestedId; } Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -432,10 +432,11 @@ { throw new ArgumentNullException("obj", "null object passed to GetCurrentLockMode"); } - var proxy = obj as INHibernateProxy; - if (proxy != null) + + if (obj.IsProxy()) { - obj = proxy.HibernateLazyInitializer.GetImplementation(this); + var proxy = obj as INHibernateProxy; + obj = proxy.HibernateLazyInitializer.GetImplementation(this); if (obj == null) { return LockMode.None; @@ -1040,10 +1041,10 @@ { using (new SessionIdLoggingContext(SessionId)) { - INHibernateProxy proxy = entity as INHibernateProxy; - if (proxy != null) + if (entity.IsProxy()) { - ILazyInitializer initializer = proxy.HibernateLazyInitializer; + INHibernateProxy proxy = entity as INHibernateProxy; + ILazyInitializer initializer = proxy.HibernateLazyInitializer; // it is possible for this method to be called during flush processing, // so make certain that we do not accidently initialize an uninitialized proxy @@ -1292,10 +1293,12 @@ using (new SessionIdLoggingContext(SessionId)) { CheckAndUpdateSessionStatus(); - var proxy = obj as INHibernateProxy; - if (proxy != null) + + if (obj.IsProxy()) { - if (!persistenceContext.ContainsProxy(proxy)) + var proxy = obj as INHibernateProxy; + + if (!persistenceContext.ContainsProxy(proxy)) { throw new TransientObjectException("proxy was not associated with the session"); } @@ -1517,10 +1520,12 @@ // Actually the case for proxies will probably work even with // the session closed, but do the check here anyway, so that // the behavior is uniform. - var proxy = obj as INHibernateProxy; - if (proxy != null) + + if (obj.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; + var proxy = obj as INHibernateProxy; + + ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.Session != this) { throw new TransientObjectException("The proxy was not associated with this session"); @@ -1547,10 +1552,11 @@ { using (new SessionIdLoggingContext(SessionId)) { - INHibernateProxy proxy = obj as INHibernateProxy; - if (proxy != null) + if (obj.IsProxy()) { - return proxy.HibernateLazyInitializer.Identifier; + INHibernateProxy proxy = obj as INHibernateProxy; + + return proxy.HibernateLazyInitializer.Identifier; } else { @@ -1942,10 +1948,12 @@ using (new SessionIdLoggingContext(SessionId)) { CheckAndUpdateSessionStatus(); - var proxy = obj as INHibernateProxy; - if (proxy != null) + + if (obj.IsProxy()) { - //do not use proxiesByKey, since not all + var proxy = obj as INHibernateProxy; + + //do not use proxiesByKey, since not all //proxies that point to this session's //instances are in that collection! ILazyInitializer li = proxy.HibernateLazyInitializer; Modified: trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -470,10 +470,10 @@ { using (new SessionIdLoggingContext(SessionId)) { - INHibernateProxy proxy = entity as INHibernateProxy; - if (proxy != null) + if (entity.IsProxy()) { - entity = proxy.HibernateLazyInitializer.GetImplementation(); + INHibernateProxy proxy = entity as INHibernateProxy; + entity = proxy.HibernateLazyInitializer.GetImplementation(); } return GuessEntityName(entity); } Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -114,10 +114,12 @@ { return InitializeField(fieldName, target); } - var nhproxy = value as INHibernateProxy; - if (nhproxy != null && unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(fieldName)) + + if (value.IsProxy() && unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(fieldName)) { - return InitializeOrGetAssociation(nhproxy, fieldName); + var nhproxy = value as INHibernateProxy; + + return InitializeOrGetAssociation(nhproxy, fieldName); } return InvokeImplementation; } Modified: trunk/nhibernate/src/NHibernate/NHibernateUtil.cs =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernateUtil.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/NHibernateUtil.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -365,7 +365,7 @@ { return; } - else if (proxy is INHibernateProxy) + else if (proxy.IsProxy()) { ((INHibernateProxy)proxy).HibernateLazyInitializer.Initialize(); } @@ -382,7 +382,7 @@ /// <returns>true if the argument is already initialized, or is not a proxy or collection</returns> public static bool IsInitialized(object proxy) { - if (proxy is INHibernateProxy) + if (proxy.IsProxy()) { return !((INHibernateProxy)proxy).HibernateLazyInitializer.IsUninitialized; } @@ -404,7 +404,7 @@ /// <returns>the true class of the instance</returns> public static System.Type GetClass(object proxy) { - if (proxy is INHibernateProxy) + if (proxy.IsProxy()) { return ((INHibernateProxy)proxy).HibernateLazyInitializer.GetImplementation().GetType(); } @@ -530,7 +530,7 @@ public static bool IsPropertyInitialized(object proxy, string propertyName) { object entity; - if (proxy is INHibernateProxy) + if (proxy.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)proxy).HibernateLazyInitializer; if (li.IsUninitialized) Modified: trunk/nhibernate/src/NHibernate/Proxy/NHibernateProxyHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/NHibernateProxyHelper.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Proxy/NHibernateProxyHelper.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -1,3 +1,4 @@ +using NHibernate.Cfg; using NHibernate.Intercept; using NHibernate.Persister.Entity; @@ -8,9 +9,9 @@ /// objects that might be instances of Classes or the Proxied version of /// the Class. /// </summary> - public sealed class NHibernateProxyHelper + public static class NHibernateProxyHelper { - private NHibernateProxyHelper() + static NHibernateProxyHelper() { //can't instantiate } @@ -23,10 +24,11 @@ /// <returns>The Underlying Type for the object regardless of if it is a Proxy.</returns> public static System.Type GetClassWithoutInitializingProxy(object obj) { - INHibernateProxy proxy = obj as INHibernateProxy; - if (proxy != null) + if (obj.IsProxy()) { - return proxy.HibernateLazyInitializer.PersistentClass; + INHibernateProxy proxy = obj as INHibernateProxy; + + return proxy.HibernateLazyInitializer.PersistentClass; } else { @@ -45,10 +47,10 @@ /// </remarks> public static System.Type GuessClass(object entity) { - var proxy = entity as INHibernateProxy; - if (proxy != null) + if (entity.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; + var proxy = entity as INHibernateProxy; + ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.IsUninitialized) { return li.PersistentClass; @@ -63,5 +65,10 @@ } return entity.GetType(); } + + public static bool IsProxy(this object entity) + { + return Environment.BytecodeProvider.ProxyFactoryFactory.IsProxy(entity); + } } } Modified: trunk/nhibernate/src/NHibernate/Type/CollectionType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/CollectionType.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Type/CollectionType.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -583,10 +583,12 @@ { object element = elem; // worrying about proxies is perhaps a little bit of overkill here... - INHibernateProxy proxy = element as INHibernateProxy; - if (proxy != null) + + if (element.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; + INHibernateProxy proxy = element as INHibernateProxy; + + ILazyInitializer li = proxy.HibernateLazyInitializer; if (!li.IsUninitialized) element = li.GetImplementation(); } Modified: trunk/nhibernate/src/NHibernate/Type/EntityType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/EntityType.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate/Type/EntityType.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -63,10 +63,11 @@ } object xid; - INHibernateProxy proxy = x as INHibernateProxy; - if (proxy!=null) + + if (x.IsProxy()) { - xid = proxy.HibernateLazyInitializer.Identifier; + INHibernateProxy proxy = x as INHibernateProxy; + xid = proxy.HibernateLazyInitializer.Identifier; } else { @@ -74,10 +75,11 @@ } object yid; - proxy = y as INHibernateProxy; - if (proxy != null) + + if (y.IsProxy()) { - yid = proxy.HibernateLazyInitializer.Identifier; + INHibernateProxy proxy = y as INHibernateProxy; + yid = proxy.HibernateLazyInitializer.Identifier; } else { @@ -139,11 +141,12 @@ /// <returns> The extracted identifier. </returns> private static object GetIdentifier(object obj, IEntityPersister persister, EntityMode entityMode) { - INHibernateProxy proxy = obj as INHibernateProxy; - if (proxy != null) + if (obj.IsProxy()) { - ILazyInitializer li = proxy.HibernateLazyInitializer; - return li.Identifier; + INHibernateProxy proxy = obj as INHibernateProxy; + ILazyInitializer li = proxy.HibernateLazyInitializer; + + return li.Identifier; } else { @@ -392,10 +395,10 @@ object proxyOrEntity = session.InternalLoad(GetAssociatedEntityName(), id, eager, IsNullable && !isProxyUnwrapEnabled); - INHibernateProxy proxy = proxyOrEntity as INHibernateProxy; - if (proxy!=null) + if (proxyOrEntity.IsProxy()) { - proxy.HibernateLazyInitializer.Unwrap = isProxyUnwrapEnabled; + INHibernateProxy proxy = proxyOrEntity as INHibernateProxy; + proxy.HibernateLazyInitializer.Unwrap = isProxyUnwrapEnabled; } return proxyOrEntity; @@ -488,10 +491,11 @@ } object id; - INHibernateProxy proxy = x as INHibernateProxy; - if (proxy!=null) + + if (x.IsProxy()) { - id = proxy.HibernateLazyInitializer.Identifier; + INHibernateProxy proxy = x as INHibernateProxy; + id = proxy.HibernateLazyInitializer.Identifier; } else { Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -23,6 +23,11 @@ return true; } - #endregion + public bool IsProxy(object entity) + { + return entity is INHibernateProxy; + } + + #endregion } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/ProxyInterface/CustomProxyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/ProxyInterface/CustomProxyFixture.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/ProxyInterface/CustomProxyFixture.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -75,7 +75,12 @@ return false; } - #endregion + public bool IsProxy(object entity) + { + return entity is INHibernateProxy; + } + + #endregion } public class DataBindingProxyFactory : ProxyFactory Modified: trunk/nhibernate/src/NHibernate.ByteCode.LinFu/ProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.LinFu/ProxyFactoryFactory.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate.ByteCode.LinFu/ProxyFactoryFactory.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -24,6 +24,11 @@ return false; } + public bool IsProxy(object entity) + { + return entity is INHibernateProxy; + } + #endregion } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs 2011-02-18 06:26:18 UTC (rev 5383) +++ trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs 2011-02-19 13:54:53 UTC (rev 5384) @@ -28,6 +28,11 @@ return false; } + public bool IsProxy(object entity) + { + return entity is INHibernateProxy; + } + #endregion } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jul...@us...> - 2011-02-24 10:05:43
|
Revision: 5394 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5394&view=rev Author: julian-maughan Date: 2011-02-24 10:05:36 +0000 (Thu, 24 Feb 2011) Log Message: ----------- Minor XML documentation refinements Modified Paths: -------------- trunk/nhibernate/src/NHibernate/ICriteria.cs trunk/nhibernate/src/NHibernate/IQuery.cs trunk/nhibernate/src/NHibernate/ISession.cs Modified: trunk/nhibernate/src/NHibernate/ICriteria.cs =================================================================== --- trunk/nhibernate/src/NHibernate/ICriteria.cs 2011-02-23 09:44:22 UTC (rev 5393) +++ trunk/nhibernate/src/NHibernate/ICriteria.cs 2011-02-24 10:05:36 UTC (rev 5394) @@ -17,38 +17,39 @@ /// where there is a variable number of conditions to be placed upon the result set. /// </para> /// <para> - /// The Session is a factory for ICriteria. Expression instances are usually obtained via + /// The Session is a factory for ICriteria. Expression instances are usually obtained via /// the factory methods on <see cref="Expression" />. eg: /// </para> /// <code> - /// IList cats = session.CreateCriteria(typeof(Cat)) - /// .Add( Expression.Like("name", "Iz%") ) - /// .Add( Expression.Gt( "weight", minWeight ) ) - /// .AddOrder( Order.Asc("age") ) - /// .List(); + /// IList cats = session.CreateCriteria(typeof(Cat)) + /// .Add(Expression.Like("name", "Iz%")) + /// .Add(Expression.Gt("weight", minWeight)) + /// .AddOrder(Order.Asc("age")) + /// .List(); /// </code> - /// You may navigate associations using <see cref="CreateAlias(string,string)" /> or <see cref="CreateCriteria(string)" />. + /// You may navigate associations using <see cref="CreateAlias(string, string)" /> + /// or <see cref="CreateCriteria(string)" />. eg: /// <code> - /// IList cats = session.CreateCriteria(typeof(Cat)) - /// .CreateCriteria("kittens") - /// .Add( Expression.like("name", "Iz%") ) - /// .List(); - /// </code> + /// IList<Cat> cats = session.CreateCriteria<Cat> + /// .CreateCriteria("kittens") + /// .Add(Expression.like("name", "Iz%")) + /// .List<Cat>(); + /// </code> /// <para> - /// You may specify projection and aggregation using <tt>Projection</tt> - /// instances obtained via the factory methods on <tt>Projections</tt>. + /// You may specify projection and aggregation using <c>Projection</c> instances obtained + /// via the factory methods on <c>Projections</c>. eg: /// <code> - /// IList cats = session.CreateCriteria(typeof(Cat)) - /// .setProjection( Projections.ProjectionList() - /// .Add( Projections.RowCount() ) - /// .Add( Projections.Avg("weight") ) - /// .Add( Projections.Max("weight") ) - /// .Add( Projections.Min("weight") ) - /// .Add( Projections.GroupProperty("color") ) - /// ) - /// .AddOrder( Order.Asc("color") ) - /// .List(); - /// </code> + /// IList<Cat> cats = session.CreateCriteria<Cat> + /// .SetProjection( + /// Projections.ProjectionList() + /// .Add(Projections.RowCount()) + /// .Add(Projections.Avg("weight")) + /// .Add(Projections.Max("weight")) + /// .Add(Projections.Min("weight")) + /// .Add(Projections.GroupProperty("color"))) + /// .AddOrder(Order.Asc("color")) + /// .List<Cat>(); + /// </code> /// </para> /// </remarks> public interface ICriteria : ICloneable @@ -82,7 +83,7 @@ ICriteria Add(ICriterion expression); /// <summary> - /// An an Order to the result set + /// An an Order to the result set /// </summary> /// <param name="order"></param> ICriteria AddOrder(Order order); @@ -148,7 +149,7 @@ ICriteria CreateCriteria(string associationPath); /// <summary> - /// Create a new <see cref="ICriteria" />, "rooted" at the associated entity, + /// Create a new <see cref="ICriteria" />, "rooted" at the associated entity, /// using the specified join type. /// </summary> /// <param name="associationPath">A dot-seperated property path</param> @@ -327,7 +328,7 @@ /// Gets the root entity type if available, throws otherwise /// </summary> /// <remarks> - /// This is an NHibernate specific method, used by several dependent + /// This is an NHibernate specific method, used by several dependent /// frameworks for advance integration with NHibernate. /// </remarks> System.Type GetRootEntityTypeIfAvailable(); Modified: trunk/nhibernate/src/NHibernate/IQuery.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQuery.cs 2011-02-23 09:44:22 UTC (rev 5393) +++ trunk/nhibernate/src/NHibernate/IQuery.cs 2011-02-24 10:05:36 UTC (rev 5394) @@ -10,39 +10,43 @@ /// An object-oriented representation of a NHibernate query. /// </summary> /// <remarks> - /// An <c>IQuery</c> instance is obtained by calling <c>ISession.CreateQuery()</c>. This interface - /// exposes some extra functionality beyond that provided by <c>ISession.Iterate()</c> and - /// <c>ISession.List()</c>; - /// <list> + /// An <c>IQuery</c> instance is obtained by calling <see cref="ISession.CreateQuery(string)" />. + /// Key features of this interface include: + /// <list type="bullet"> /// <item> - /// A particular page of the result set may be selected by calling - /// <c>SetMaxResults()</c>, <c>SetFirstResult()</c>. The generated sql + /// Paging: A particular page of the result set may be selected by calling + /// <see cref="SetMaxResults(int)" />, <see cref="SetFirstResult(int)" />. The generated SQL /// depends on the capabilities of the <see cref="Dialect.Dialect"/>. Some /// Dialects are for databases that have built in paging (LIMIT) and those capabilities - /// will be used to limit the number of records returned by the sql statement. + /// will be used to limit the number of records returned by the SQL statement. /// If the database does not support LIMITs then all of the records will be returned, /// but the objects created will be limited to the specific results requested. /// </item> - /// <item>Named query parameters may be used</item> + /// <item> + /// Named parameters + /// </item> + /// <item> + /// Ability to return 'read-only' entities + /// </item> /// </list> /// <para> - /// Named query parameters are tokens of the form <c>:name</c> in the query string. A value is bound - /// to the <c>Int32</c> parameter <c>:foo</c> by calling + /// Named query parameters are tokens of the form <c>:name</c> in the query string. For example, a + /// value is bound to the <c>Int32</c> parameter <c>:foo</c> by calling: /// <code> - /// SetParameter("foo", foo, NHibernateUtil.Int32); + /// SetParameter("foo", foo, NHibernateUtil.Int32); /// </code> - /// for example. A name may appear multiple times in the query string. + /// A name may appear multiple times in the query string. /// </para> /// <para> - /// Unnamed parameters <c>?</c> are also supported. To bind a value to an unnamed - /// parameter use a Set method that accepts an <c>Int32</c> positional argument - numbered from - /// zero. + /// Unnamed parameters <c>?</c> are also supported. To bind a value to an unnamed + /// parameter use a Set method that accepts an <c>Int32</c> positional argument - numbered from + /// zero. /// </para> /// <para> /// You may not mix and match unnamed parameters and named parameters in the same query. /// </para> /// <para> - /// Queries are executed by calling <c>List()</c> or <c>Iterate()</c>. A query + /// Queries are executed by calling <see cref="IQuery.List()" /> or <see cref="IQuery.Enumerable()" />. A query /// may be re-executed by subsequent invocations. Its lifespan is, however, bounded by the lifespan /// of the <c>ISession</c> that created it. /// </para> Modified: trunk/nhibernate/src/NHibernate/ISession.cs =================================================================== --- trunk/nhibernate/src/NHibernate/ISession.cs 2011-02-23 09:44:22 UTC (rev 5393) +++ trunk/nhibernate/src/NHibernate/ISession.cs 2011-02-24 10:05:36 UTC (rev 5394) @@ -20,16 +20,16 @@ /// <para> /// The main function of the <c>ISession</c> is to offer create, find and delete operations /// for instances of mapped entity classes. Instances may exist in one of two states: - /// <list> - /// <item>transient: not associated with any <c>ISession</c></item> - /// <item>persistent: associated with a <c>ISession</c></item> + /// <list type="bullet"> + /// <item>transient: not associated with any <c>ISession</c></item> + /// <item>persistent: associated with a <c>ISession</c></item> /// </list> /// </para> /// <para> - /// Transient instances may be made persistent by calling <c>Save()</c>, <c>Insert()</c>, - /// or <c>Update()</c>. Persistent instances may be made transient by calling <c>Delete()</c>. - /// Any instance returned by a <c>List()</c>, <c>Iterate()</c>, <c>Load()</c>, or <c>Create</c> - /// method is persistent. + /// Transient instances may be made persistent by calling <c>Save()</c>, <c>Insert()</c>, + /// or <c>Update()</c>. Persistent instances may be made transient by calling <c>Delete()</c>. + /// Any instance returned by a <c>List()</c>, <c>Enumerable()</c>, <c>Load()</c>, or <c>Create()</c> + /// method is persistent. /// </para> /// <para> /// <c>Save()</c> results in an SQL <c>INSERT</c>, <c>Delete()</c> @@ -46,26 +46,28 @@ /// </para> /// <para> /// A typical transaction should use the following idiom: - /// <code> - /// ISession sess = factory.OpenSession(); - /// ITransaction tx; - /// try { - /// tx = sess.BeginTransaction(); - /// //do some work + /// <code> + /// using (ISession session = factory.OpenSession()) + /// using (ITransaction tx = session.BeginTransaction()) + /// { + /// try + /// { + /// // do some work /// ... /// tx.Commit(); - /// } catch (Exception e) { + /// } + /// catch (Exception e) + /// { /// if (tx != null) tx.Rollback(); /// throw; - /// } finally { - /// sess.Close(); /// } - /// </code> + /// } + /// </code> /// </para> /// <para> - /// If the <c>ISession</c> throws an exception, the transaction must be rolled back and the session - /// discarded. The internal state of the <c>ISession</c> might not be consistent with the database - /// after the exception occurs. + /// If the <c>ISession</c> throws an exception, the transaction must be rolled back and the session + /// discarded. The internal state of the <c>ISession</c> might not be consistent with the database + /// after the exception occurs. /// </para> /// <seealso cref="ISessionFactory"/> /// </remarks> @@ -215,9 +217,9 @@ /// <returns>the persistent instance</returns> object Load(System.Type theType, object id, LockMode lockMode); - /// <summary> + /// <summary> /// Return the persistent instance of the given entity class with the given identifier, - /// obtaining the specified lock mode, assuming the instance exists. + /// obtaining the specified lock mode, assuming the instance exists. /// </summary> /// <param name="entityName">The entity-name of a persistent class</param> /// <param name="id">a valid identifier of an existing persistent instance of the class </param> @@ -263,7 +265,7 @@ /// <returns>The persistent instance or proxy</returns> T Load<T>(object id); - /// <summary> + /// <summary> /// Return the persistent instance of the given <paramref name="entityName"/> with the given identifier, /// assuming that the instance exists. /// </summary> @@ -278,7 +280,7 @@ object Load(string entityName, object id); /// <summary> - /// Read the persistent state associated with the given identifier into the given transient + /// Read the persistent state associated with the given identifier into the given transient /// instance. /// </summary> /// <param name="obj">An "empty" instance of the persistent class</param> @@ -286,17 +288,17 @@ void Load(object obj, object id); /// <summary> - /// Persist all reachable transient objects, reusing the current identifier + /// Persist all reachable transient objects, reusing the current identifier /// values. Note that this will not trigger the Interceptor of the Session. /// </summary> /// <param name="obj">a detached instance of a persistent class</param> /// <param name="replicationMode"></param> void Replicate(object obj, ReplicationMode replicationMode); - /// <summary> + /// <summary> /// Persist the state of the given detached instance, reusing the current /// identifier value. This operation cascades to associated instances if - /// the association is mapped with <tt>cascade="replicate"</tt>. + /// the association is mapped with <tt>cascade="replicate"</tt>. /// </summary> /// <param name="entityName"></param> /// <param name="obj">a detached instance of a persistent class </param> @@ -331,7 +333,7 @@ /// <returns> the generated identifier </returns> /// <remarks> /// This operation cascades to associated instances if the - /// association is mapped with <tt>cascade="save-update"</tt>. + /// association is mapped with <tt>cascade="save-update"</tt>. /// </remarks> object Save(string entityName, object obj); @@ -346,7 +348,7 @@ /// <param name="obj">A transient instance containing new or updated state</param> void SaveOrUpdate(object obj); - /// <summary> + /// <summary> /// Either <see cref="Save(String,Object)"/> or <see cref="Update(String,Object)"/> /// the given instance, depending upon resolution of the unsaved-value checks /// (see the manual for discussion of unsaved-value checking). @@ -357,7 +359,7 @@ /// <seealso cref="ISession.Update(String,Object)"/> /// <remarks> /// This operation cascades to associated instances if the association is mapped - /// with <tt>cascade="save-update"</tt>. + /// with <tt>cascade="save-update"</tt>. /// </remarks> void SaveOrUpdate(string entityName, object obj); @@ -382,20 +384,20 @@ /// <param name="id">Identifier of persistent instance</param> void Update(object obj, object id); - /// <summary> + /// <summary> /// Update the persistent instance with the identifier of the given detached - /// instance. + /// instance. /// </summary> /// <param name="entityName">The Entity name.</param> /// <param name="obj">a detached instance containing updated state </param> /// <remarks> /// If there is a persistent instance with the same identifier, /// an exception is thrown. This operation cascades to associated instances - /// if the association is mapped with <tt>cascade="save-update"</tt>. + /// if the association is mapped with <tt>cascade="save-update"</tt>. /// </remarks> void Update(string entityName, object obj); - /// <summary> + /// <summary> /// Copy the state of the given object onto the persistent object with the same /// identifier. If there is no persistent instance currently associated with /// the session, it will be loaded. Return the persistent instance. If the @@ -403,7 +405,7 @@ /// instance. The given instance does not become associated with the session. /// This operation cascades to associated instances if the association is mapped /// with <tt>cascade="merge"</tt>.<br/> - /// The semantics of this method are defined by JSR-220. + /// The semantics of this method are defined by JSR-220. /// </summary> /// <param name="obj">a detached instance with state to be copied </param> /// <returns> an updated persistent instance </returns> @@ -425,10 +427,10 @@ /// <returns></returns> object Merge(string entityName, object obj); - /// <summary> + /// <summary> /// Make a transient instance persistent. This operation cascades to associated /// instances if the association is mapped with <tt>cascade="persist"</tt>.<br/> - /// The semantics of this method are defined by JSR-220. + /// The semantics of this method are defined by JSR-220. /// </summary> /// <param name="obj">a transient instance to be made persistent </param> void Persist(object obj); @@ -444,9 +446,9 @@ /// <summary> /// Copy the state of the given object onto the persistent object with the same - /// identifier. If there is no persistent instance currently associated with - /// the session, it will be loaded. Return the persistent instance. If the - /// given instance is unsaved or does not exist in the database, save it and + /// identifier. If there is no persistent instance currently associated with + /// the session, it will be loaded. Return the persistent instance. If the + /// given instance is unsaved or does not exist in the database, save it and /// return it as a newly persistent instance. Otherwise, the given instance /// does not become associated with the session. /// </summary> @@ -456,8 +458,8 @@ object SaveOrUpdateCopy(object obj); /// <summary> - /// Copy the state of the given object onto the persistent object with the - /// given identifier. If there is no persistent instance currently associated + /// Copy the state of the given object onto the persistent object with the + /// given identifier. If there is no persistent instance currently associated /// with the session, it will be loaded. Return the persistent instance. If /// there is no database row with the given identifier, save the given instance /// and return it as a newly persistent instance. Otherwise, the given instance @@ -484,7 +486,7 @@ /// an instance associated with the receiving <see cref="ISession"/> or a transient /// instance with an identifier associated with existing persistent state. /// This operation cascades to associated instances if the association is mapped - /// with <tt>cascade="delete"</tt>. + /// with <tt>cascade="delete"</tt>. /// </summary> /// <param name="entityName">The entity name for the instance to be removed. </param> /// <param name="obj">the instance to be removed </param> @@ -522,8 +524,8 @@ /// <param name="lockMode">The lock level</param> void Lock(object obj, LockMode lockMode); - /// <summary> - /// Obtain the specified lock level upon the given object. + /// <summary> + /// Obtain the specified lock level upon the given object. /// </summary> /// <param name="entityName">The Entity name.</param> /// <param name="obj">a persistent or transient instance </param> @@ -629,8 +631,8 @@ /// <returns>An ICriteria object</returns> ICriteria CreateCriteria(System.Type persistentClass, string alias); - /// <summary> - /// Create a new <c>Criteria</c> instance, for the given entity name. + /// <summary> + /// Create a new <c>Criteria</c> instance, for the given entity name. /// </summary> /// <param name="entityName">The name of the entity to Query</param> /// <returns>An ICriteria object</returns> @@ -638,7 +640,7 @@ /// <summary> /// Create a new <c>Criteria</c> instance, for the given entity name, - /// with the given alias. + /// with the given alias. /// </summary> /// <param name="entityName">The name of the entity to Query</param> /// <param name="alias">The alias of the entity</param> @@ -720,10 +722,10 @@ /// <returns>a persistent instance or null</returns> object Get(System.Type clazz, object id, LockMode lockMode); - /// <summary> + /// <summary> /// Return the persistent instance of the given named entity with the given identifier, /// or null if there is no such persistent instance. (If the instance, or a proxy for the - /// instance, is already associated with the session, return that instance or proxy.) + /// instance, is already associated with the session, return that instance or proxy.) /// </summary> /// <param name="entityName">the entity name </param> /// <param name="id">an identifier </param> @@ -740,7 +742,7 @@ /// </summary> T Get<T>(object id, LockMode lockMode); - /// <summary> + /// <summary> /// Return the entity name for a persistent entity /// </summary> /// <param name="obj">a persistent entity</param> @@ -794,7 +796,7 @@ /// Implementors of the <seealso cref="ISession"/> interface should return the NHibernate implementation of this method. /// </remarks> /// <returns> - /// An NHibernate implementation of the <seealso cref="ISessionImplementor"/> interface + /// An NHibernate implementation of the <seealso cref="ISessionImplementor"/> interface /// </returns> ISessionImplementor GetSessionImplementation(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jul...@us...> - 2011-02-26 05:56:33
|
Revision: 5399 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5399&view=rev Author: julian-maughan Date: 2011-02-26 05:56:26 +0000 (Sat, 26 Feb 2011) Log Message: ----------- Fixed SessionException ("Session was already closed!") that occurs when disposing a stateless session that has been closed (ref. NH-2549). Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs trunk/nhibernate/src/NHibernate.Test/Stateless/StatelessSessionFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-25 09:49:31 UTC (rev 5398) +++ trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-26 05:56:26 UTC (rev 5399) @@ -438,7 +438,7 @@ { get { return false; } } - + public override object GetEntityUsingInterceptor(EntityKey key) { CheckAndUpdateSessionStatus(); @@ -472,7 +472,7 @@ { if (entity.IsProxy()) { - INHibernateProxy proxy = entity as INHibernateProxy; + INHibernateProxy proxy = entity as INHibernateProxy; entity = proxy.HibernateLazyInitializer.GetImplementation(); } return GuessEntityName(entity); @@ -551,7 +551,7 @@ /// Implementors of the <seealso cref="IStatelessSession"/> interface should return the NHibernate implementation of this method. /// </remarks> /// <returns> - /// An NHibernate implementation of the <seealso cref="ISessionImplementor"/> interface + /// An NHibernate implementation of the <seealso cref="ISessionImplementor"/> interface /// </returns> public ISessionImplementor GetSessionImplementation() { @@ -981,7 +981,7 @@ // free managed resources that are being managed by the session if we // know this call came through Dispose() - if (isDisposing) + if (isDisposing && !IsClosed) { Close(); } Modified: trunk/nhibernate/src/NHibernate.Test/Stateless/StatelessSessionFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Stateless/StatelessSessionFixture.cs 2011-02-25 09:49:31 UTC (rev 5398) +++ trunk/nhibernate/src/NHibernate.Test/Stateless/StatelessSessionFixture.cs 2011-02-26 05:56:26 UTC (rev 5399) @@ -211,5 +211,20 @@ criteria.Executing(c => c.List()).NotThrows(); } } + + [Test] + public void DisposingClosedStatelessSessionShouldNotCauseSessionException() + { + try + { + IStatelessSession ss = sessions.OpenStatelessSession(); + ss.Close(); + ss.Dispose(); + } + catch (SessionException) + { + Assert.Fail(); + } + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-02-26 10:38:13
|
Revision: 5400 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5400&view=rev Author: ricbrown Date: 2011-02-26 10:38:07 +0000 (Sat, 26 Feb 2011) Log Message: ----------- Fix NH-2543 (IQueryOver support is not implemented for IStatelessSession) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/IStatelessSession.cs trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs Modified: trunk/nhibernate/src/NHibernate/IStatelessSession.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IStatelessSession.cs 2011-02-26 05:56:26 UTC (rev 5399) +++ trunk/nhibernate/src/NHibernate/IStatelessSession.cs 2011-02-26 10:38:07 UTC (rev 5400) @@ -1,6 +1,6 @@ using System; using System.Data; - +using System.Linq.Expressions; using NHibernate.Engine; namespace NHibernate @@ -194,6 +194,20 @@ ICriteria CreateCriteria(string entityName, string alias); /// <summary> + /// Creates a new <c>IQueryOver<T></c> for the entity class. + /// </summary> + /// <typeparam name="T">The entity class</typeparam> + /// <returns>An ICriteria<T> object</returns> + IQueryOver<T,T> QueryOver<T>() where T : class; + + /// <summary> + /// Creates a new <c>IQueryOver<T></c> for the entity class. + /// </summary> + /// <typeparam name="T">The entity class</typeparam> + /// <returns>An ICriteria<T> object</returns> + IQueryOver<T,T> QueryOver<T>(Expression<Func<T>> alias) where T : class; + + /// <summary> /// Create a new instance of <see cref="ISQLQuery"/> for the given SQL query string. /// Entities returned by the query are detached. /// </summary> Modified: trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-26 05:56:26 UTC (rev 5399) +++ trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2011-02-26 10:38:07 UTC (rev 5400) @@ -2,10 +2,11 @@ using System.Collections; using System.Collections.Generic; using System.Data; - +using System.Linq.Expressions; using NHibernate.AdoNet; using NHibernate.Cache; using NHibernate.Collection; +using NHibernate.Criterion; using NHibernate.Engine; using NHibernate.Engine.Query; using NHibernate.Engine.Query.Sql; @@ -915,6 +916,25 @@ } } + public IQueryOver<T,T> QueryOver<T>() where T : class + { + using (new SessionIdLoggingContext(SessionId)) + { + CheckAndUpdateSessionStatus(); + return new QueryOver<T,T>(new CriteriaImpl(typeof(T), this)); + } + } + + public IQueryOver<T,T> QueryOver<T>(Expression<Func<T>> alias) where T : class + { + using (new SessionIdLoggingContext(SessionId)) + { + CheckAndUpdateSessionStatus(); + string aliasPath = ExpressionProcessor.FindMemberExpression(alias.Body); + return new QueryOver<T,T>(new CriteriaImpl(typeof(T), aliasPath, this)); + } + } + /// <summary> /// Begin a NHibernate transaction /// </summary> Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-02-26 05:56:26 UTC (rev 5399) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-02-26 10:38:07 UTC (rev 5400) @@ -552,6 +552,34 @@ } } + [Test] + public void StatelessSession() + { + using (var ss = sessions.OpenStatelessSession()) + { + using (var tx = ss.BeginTransaction()) + { + var person = new Person() { Name = "test1" }; + ss.Insert(person); + + var statelessPerson1 = + ss.QueryOver<Person>() + .List() + [0]; + + Assert.That(statelessPerson1.Id, Is.EqualTo(person.Id)); + + var statelessPerson2 = + QueryOver.Of<Person>() + .GetExecutableQueryOver(ss) + .List() + [0]; + + Assert.That(statelessPerson2.Id, Is.EqualTo(person.Id)); + } + } + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-03-02 22:20:30
|
Revision: 5414 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5414&view=rev Author: ricbrown Date: 2011-03-02 22:20:24 +0000 (Wed, 02 Mar 2011) Log Message: ----------- Fix NH-2400 (Linq query fail when using contains from an empty Collection) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -1,5 +1,5 @@ +using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -82,6 +82,8 @@ // Nulls generate different query plans. X = variable generates a different query depending on if variable is null or not. if (param.Value == null) _string.Append("NULL"); + if (param.Value is ICollection && ((ICollection)param.Value).Count == 0) + _string.Append("EmptyList"); else _string.Append(param.Name); } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections; +using System.Linq; using NHibernate.Hql.Ast; using Remotion.Data.Linq.Clauses.ResultOperators; @@ -18,7 +19,15 @@ if (source is HqlParameter) { // This is an "in" style statement - tree.SetRoot(tree.TreeBuilder.In(itemExpression, source)); + if (IsEmptyList((HqlParameter)source, queryModelVisitor.VisitorParameters)) + { + // if the list is empty the expression will always be false, so generate "1 = 0" + tree.SetRoot(tree.TreeBuilder.Equality(tree.TreeBuilder.Constant(1), tree.TreeBuilder.Constant(0))); + } + else + { + tree.SetRoot(tree.TreeBuilder.In(itemExpression, source)); + } } else { @@ -39,5 +48,12 @@ { return node.NodesPreOrder.Single(n => n is HqlRange).Children.Single(n => n is HqlAlias) as HqlAlias; } + + private static bool IsEmptyList(HqlParameter source, VisitorParameters parameters) + { + var parameterName = source.NodesPreOrder.Single(n => n is HqlIdent).AstNode.Text; + var parameterValue = parameters.ConstantToParameterMap.Single(p => p.Value.Name == parameterName).Key.Value; + return ((ICollection)parameterValue).Count == 0; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -327,6 +327,18 @@ } [Test] + public void UsersWithEmptyList_NH2400() + { + var names = new List<string>(); + + var query = (from user in db.Users + where names.Contains(user.Name) + select user).ToList(); + + Assert.That(query.Count, Is.EqualTo(0)); + } + + [Test] public void WhenTheSourceOfConstantIsICollectionThenNoThrows() { ICollection<string> names = new List<string> {"ayende", "rahien"}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-03-03 22:37:31
|
Revision: 5415 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5415&view=rev Author: ricbrown Date: 2011-03-03 22:37:25 +0000 (Thu, 03 Mar 2011) Log Message: ----------- Fix NH-2400 (Linq query fail when using contains from an empty Collection) - updated fix to handle IEnumerable (thanks to Patrick for spotting it) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-02 22:20:24 UTC (rev 5414) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-03 22:37:25 UTC (rev 5415) @@ -82,7 +82,7 @@ // Nulls generate different query plans. X = variable generates a different query depending on if variable is null or not. if (param.Value == null) _string.Append("NULL"); - if (param.Value is ICollection && ((ICollection)param.Value).Count == 0) + if (param.Value is IEnumerable && !((IEnumerable)param.Value).Cast<object>().Any()) _string.Append("EmptyList"); else _string.Append(param.Name); Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-02 22:20:24 UTC (rev 5414) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-03 22:37:25 UTC (rev 5415) @@ -53,7 +53,7 @@ { var parameterName = source.NodesPreOrder.Single(n => n is HqlIdent).AstNode.Text; var parameterValue = parameters.ConstantToParameterMap.Single(p => p.Value.Name == parameterName).Key.Value; - return ((ICollection)parameterValue).Count == 0; + return !((IEnumerable)parameterValue).Cast<object>().Any(); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-02 22:20:24 UTC (rev 5414) +++ trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-03 22:37:25 UTC (rev 5415) @@ -339,6 +339,32 @@ } [Test] + public void UsersWithEmptyEnumerable() + { + var allNames = new List<string> { "ayende", "rahien" }; + var names = allNames.Where(n => n == "does not exist"); + + var query = (from user in db.Users + where names.Contains(user.Name) + select user).ToList(); + + Assert.That(query.Count, Is.EqualTo(0)); + } + + [Test] + [Ignore("inline empty list expression does not evaluate correctly")] + public void UsersWithEmptyInlineEnumerable() + { + var allNames = new List<string> { "ayende", "rahien" }; + + var query = (from user in db.Users + where allNames.Where(n => n == "does not exist").Contains(user.Name) + select user).ToList(); + + Assert.That(query.Count, Is.EqualTo(0)); + } + + [Test] public void WhenTheSourceOfConstantIsICollectionThenNoThrows() { ICollection<string> names = new List<string> {"ayende", "rahien"}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-03-04 16:51:25
|
Revision: 5416 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5416&view=rev Author: ricbrown Date: 2011-03-04 16:51:18 +0000 (Fri, 04 Mar 2011) Log Message: ----------- Fix NH-2172 (Unrecognised method call in expression when using QueryOver queries in VB.Net) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-03 22:37:25 UTC (rev 5415) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-04 16:51:18 UTC (rev 5416) @@ -312,6 +312,9 @@ private static ICriterion ProcessSimpleExpression(BinaryExpression be) { + if (be.Left.NodeType == ExpressionType.Call && ((MethodCallExpression)be.Left).Method.Name == "CompareString") + return ProcessVisualBasicStringComparison(be); + string property = FindMemberExpression(be.Left); System.Type propertyType = FindMemberType(be.Left); @@ -329,6 +332,22 @@ return criterion; } + private static ICriterion ProcessVisualBasicStringComparison(BinaryExpression be) + { + var methodCall = (MethodCallExpression)be.Left; + switch(be.NodeType) + { + case ExpressionType.Equal: + return ProcessSimpleExpression(Expression.Equal(methodCall.Arguments[0], methodCall.Arguments[1])); + + case ExpressionType.NotEqual: + return ProcessSimpleExpression(Expression.NotEqual(methodCall.Arguments[0], methodCall.Arguments[1])); + + default: + throw new Exception("Unhandled expression: " + be); + } + } + private static ICriterion ProcessSimpleNullExpression(string property, ExpressionType expressionType) { if (expressionType == ExpressionType.Equal) Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-03 22:37:25 UTC (rev 5415) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-04 16:51:18 UTC (rev 5416) @@ -44,7 +44,29 @@ AssertCriteriaAreEqual(expected, actual); } + public static int CompareString(string left, string right, bool textCompare) + { + // could consider calling Microsoft.VisualBasic.CompilerServices.Operators.CompareString + throw new Exception("This is just here to allow us to simulate the VB.Net LINQ expression tree"); + } + [Test] + public void StringEqualityInVisualBasic() + { + ICriteria expected = + CreateTestCriteria(typeof(Person)) + .Add(Restrictions.Eq("Name", "test name")) + .Add(Restrictions.Not(Restrictions.Eq("Name", "test name"))); + + IQueryOver<Person> actual = + CreateTestQueryOver<Person>() + .And(p => CompareString(p.Name, "test name", true) == 0) + .And(p => CompareString(p.Name, "test name", true) != 0); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] public void PropertyCriterion_NoAlias() { ICriteria expected = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-03-05 08:01:08
|
Revision: 5421 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5421&view=rev Author: ricbrown Date: 2011-03-05 08:01:01 +0000 (Sat, 05 Mar 2011) Log Message: ----------- Fix NH-2172 (Unrecognised method call in expression when using QueryOver queries in VB.Net) - updated fix to handle other comparisons (<, <=, >, >=) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-04 22:51:08 UTC (rev 5420) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-05 08:01:01 UTC (rev 5421) @@ -315,19 +315,24 @@ if (be.Left.NodeType == ExpressionType.Call && ((MethodCallExpression)be.Left).Method.Name == "CompareString") return ProcessVisualBasicStringComparison(be); - string property = FindMemberExpression(be.Left); - System.Type propertyType = FindMemberType(be.Left); + return ProcessSimpleExpression(be.Left, be.Right, be.NodeType); + } - object value = FindValue(be.Right); + public static ICriterion ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType) + { + string property = FindMemberExpression(left); + System.Type propertyType = FindMemberType(left); + + object value = FindValue(right); value = ConvertType(value, propertyType); if (value == null) - return ProcessSimpleNullExpression(property, be.NodeType); + return ProcessSimpleNullExpression(property, nodeType); - if (!_simpleExpressionCreators.ContainsKey(be.NodeType)) - throw new Exception("Unhandled simple expression type: " + be.NodeType); + if (!_simpleExpressionCreators.ContainsKey(nodeType)) + throw new Exception("Unhandled simple expression type: " + nodeType); - Func<string, object, ICriterion> simpleExpressionCreator = _simpleExpressionCreators[be.NodeType]; + Func<string, object, ICriterion> simpleExpressionCreator = _simpleExpressionCreators[nodeType]; ICriterion criterion = simpleExpressionCreator(property, value); return criterion; } @@ -335,17 +340,7 @@ private static ICriterion ProcessVisualBasicStringComparison(BinaryExpression be) { var methodCall = (MethodCallExpression)be.Left; - switch(be.NodeType) - { - case ExpressionType.Equal: - return ProcessSimpleExpression(Expression.Equal(methodCall.Arguments[0], methodCall.Arguments[1])); - - case ExpressionType.NotEqual: - return ProcessSimpleExpression(Expression.NotEqual(methodCall.Arguments[0], methodCall.Arguments[1])); - - default: - throw new Exception("Unhandled expression: " + be); - } + return ProcessSimpleExpression(methodCall.Arguments[0], methodCall.Arguments[1], be.NodeType); } private static ICriterion ProcessSimpleNullExpression(string property, ExpressionType expressionType) Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-04 22:51:08 UTC (rev 5420) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-05 08:01:01 UTC (rev 5421) @@ -56,12 +56,20 @@ ICriteria expected = CreateTestCriteria(typeof(Person)) .Add(Restrictions.Eq("Name", "test name")) - .Add(Restrictions.Not(Restrictions.Eq("Name", "test name"))); + .Add(Restrictions.Not(Restrictions.Eq("Name", "test name"))) + .Add(Restrictions.Gt("Name", "test name")) + .Add(Restrictions.Ge("Name", "test name")) + .Add(Restrictions.Lt("Name", "test name")) + .Add(Restrictions.Le("Name", "test name")); IQueryOver<Person> actual = CreateTestQueryOver<Person>() .And(p => CompareString(p.Name, "test name", true) == 0) - .And(p => CompareString(p.Name, "test name", true) != 0); + .And(p => CompareString(p.Name, "test name", true) != 0) + .And(p => CompareString(p.Name, "test name", true) > 0) + .And(p => CompareString(p.Name, "test name", true) >= 0) + .And(p => CompareString(p.Name, "test name", true) < 0) + .And(p => CompareString(p.Name, "test name", true) <= 0); AssertCriteriaAreEqual(expected, actual); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-03-05 10:51:27
|
Revision: 5422 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5422&view=rev Author: ricbrown Date: 2011-03-05 10:51:21 +0000 (Sat, 05 Mar 2011) Log Message: ----------- Fix NH-2172 (Unrecognised method call in expression when using QueryOver queries in VB.Net) - updated fix to handle property comparisons Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-05 08:01:01 UTC (rev 5421) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-03-05 10:51:21 UTC (rev 5422) @@ -318,7 +318,7 @@ return ProcessSimpleExpression(be.Left, be.Right, be.NodeType); } - public static ICriterion ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType) + private static ICriterion ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType) { string property = FindMemberExpression(left); System.Type propertyType = FindMemberType(left); @@ -340,7 +340,11 @@ private static ICriterion ProcessVisualBasicStringComparison(BinaryExpression be) { var methodCall = (MethodCallExpression)be.Left; - return ProcessSimpleExpression(methodCall.Arguments[0], methodCall.Arguments[1], be.NodeType); + + if (IsMemberExpression(methodCall.Arguments[1])) + return ProcessMemberExpression(methodCall.Arguments[0], methodCall.Arguments[1], be.NodeType); + else + return ProcessSimpleExpression(methodCall.Arguments[0], methodCall.Arguments[1], be.NodeType); } private static ICriterion ProcessSimpleNullExpression(string property, ExpressionType expressionType) @@ -357,13 +361,18 @@ private static ICriterion ProcessMemberExpression(BinaryExpression be) { - string leftProperty = FindMemberExpression(be.Left); - string rightProperty = FindMemberExpression(be.Right); + return ProcessMemberExpression(be.Left, be.Right, be.NodeType); + } - if (!_propertyExpressionCreators.ContainsKey(be.NodeType)) - throw new Exception("Unhandled property expression type: " + be.NodeType); + private static ICriterion ProcessMemberExpression(Expression left, Expression right, ExpressionType nodeType) + { + string leftProperty = FindMemberExpression(left); + string rightProperty = FindMemberExpression(right); - Func<string, string, ICriterion> propertyExpressionCreator = _propertyExpressionCreators[be.NodeType]; + if (!_propertyExpressionCreators.ContainsKey(nodeType)) + throw new Exception("Unhandled property expression type: " + nodeType); + + Func<string, string, ICriterion> propertyExpressionCreator = _propertyExpressionCreators[nodeType]; ICriterion criterion = propertyExpressionCreator(leftProperty, rightProperty); return criterion; } Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-05 08:01:01 UTC (rev 5421) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2011-03-05 10:51:21 UTC (rev 5422) @@ -51,7 +51,7 @@ } [Test] - public void StringEqualityInVisualBasic() + public void VisualBasicStringComparison() { ICriteria expected = CreateTestCriteria(typeof(Person)) @@ -60,7 +60,13 @@ .Add(Restrictions.Gt("Name", "test name")) .Add(Restrictions.Ge("Name", "test name")) .Add(Restrictions.Lt("Name", "test name")) - .Add(Restrictions.Le("Name", "test name")); + .Add(Restrictions.Le("Name", "test name")) + .Add(Restrictions.EqProperty("Name", "Name")) + .Add(Restrictions.Not(Restrictions.EqProperty("Name", "Name"))) + .Add(Restrictions.GtProperty("Name", "Name")) + .Add(Restrictions.GeProperty("Name", "Name")) + .Add(Restrictions.LtProperty("Name", "Name")) + .Add(Restrictions.LeProperty("Name", "Name")); IQueryOver<Person> actual = CreateTestQueryOver<Person>() @@ -69,7 +75,13 @@ .And(p => CompareString(p.Name, "test name", true) > 0) .And(p => CompareString(p.Name, "test name", true) >= 0) .And(p => CompareString(p.Name, "test name", true) < 0) - .And(p => CompareString(p.Name, "test name", true) <= 0); + .And(p => CompareString(p.Name, "test name", true) <= 0) + .And(p => CompareString(p.Name, p.Name, true) == 0) + .And(p => CompareString(p.Name, p.Name, true) != 0) + .And(p => CompareString(p.Name, p.Name, true) > 0) + .And(p => CompareString(p.Name, p.Name, true) >= 0) + .And(p => CompareString(p.Name, p.Name, true) < 0) + .And(p => CompareString(p.Name, p.Name, true) <= 0); AssertCriteriaAreEqual(expected, actual); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-05 13:04:01
|
Revision: 5423 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5423&view=rev Author: fabiomaulo Date: 2011-03-05 13:03:55 +0000 (Sat, 05 Mar 2011) Log Message: ----------- Fix NH-2482 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/NHibernate.ByteCode.Castle.Tests.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs Modified: trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2011-03-05 10:51:21 UTC (rev 5422) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2011-03-05 13:03:55 UTC (rev 5423) @@ -1,8 +1,10 @@ -using Iesi.Collections.Generic; +using System; +using Iesi.Collections.Generic; using NHibernate.Engine; namespace NHibernate.Intercept { + [Serializable] public class DefaultFieldInterceptor : AbstractFieldInterceptor { public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> unwrapProxyFieldNames, string entityName, System.Type mappedClass) Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs 2011-03-05 10:51:21 UTC (rev 5422) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs 2011-03-05 13:03:55 UTC (rev 5423) @@ -1,3 +1,4 @@ +using System; using Castle.DynamicProxy; using NHibernate.Intercept; using NHibernate.Util; @@ -4,6 +5,7 @@ namespace NHibernate.ByteCode.Castle { + [Serializable] public class LazyFieldInterceptor : IFieldInterceptorAccessor, global::Castle.DynamicProxy.IInterceptor { public IFieldInterceptor FieldInterceptor Added: trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs 2011-03-05 13:03:55 UTC (rev 5423) @@ -0,0 +1,35 @@ +using System; +using Iesi.Collections.Generic; +using NHibernate.Intercept; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.ByteCode.Castle.Tests +{ + public class LazyFieldInterceptorSerializable + { + [Serializable] + public class MyClass + { + public virtual int Id { get; set; } + } + + [Test] + public void LazyFieldInterceptorMarkedAsSerializable() + { + typeof(LazyFieldInterceptor).Should().Have.Attribute<SerializableAttribute>(); + } + + [Test] + public void LazyFieldInterceptorIsBinarySerializable() + { + var pf = new ProxyFactory(); + var propertyInfo = typeof(MyClass).GetProperty("Id"); + pf.PostInstantiate("MyClass", typeof(MyClass), new HashedSet<System.Type>(), propertyInfo.GetGetMethod(), propertyInfo.GetSetMethod(), null); + var fieldInterceptionProxy = (IFieldInterceptorAccessor)pf.GetFieldInterceptionProxy(); + fieldInterceptionProxy.FieldInterceptor = new DefaultFieldInterceptor(null, null, null, "MyClass", typeof(MyClass)); + + fieldInterceptionProxy.Should().Be.BinarySerializable(); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/NHibernate.ByteCode.Castle.Tests.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/NHibernate.ByteCode.Castle.Tests.csproj 2011-03-05 10:51:21 UTC (rev 5422) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/NHibernate.ByteCode.Castle.Tests.csproj 2011-03-05 13:03:55 UTC (rev 5423) @@ -70,6 +70,9 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\..\lib\net\3.5\nunit.framework.dll</HintPath> </Reference> + <Reference Include="SharpTestsEx.NUnit"> + <HintPath>..\..\lib\net\3.5\SharpTestsEx.NUnit.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.Core"> <RequiredTargetFramework>3.5</RequiredTargetFramework> @@ -80,6 +83,7 @@ <ItemGroup> <Compile Include="DebugConnectionProvider.cs" /> <Compile Include="AssemblyInfo.cs" /> + <Compile Include="LazyFieldInterceptorSerializable.cs" /> <Compile Include="ProxyInterface\CastleProxy.cs" /> <Compile Include="ProxyInterface\CastleProxyFixture.cs" /> <Compile Include="ProxyInterface\CastleProxyImpl.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-03-06 20:39:35
|
Revision: 5438 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5438&view=rev Author: patearl Date: 2011-03-06 20:39:29 +0000 (Sun, 06 Mar 2011) Log Message: ----------- SQLite: Added "iff" function. Ignore some unsupported tests. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/SQLExceptionConversionTest.cs trunk/nhibernate/src/NHibernate.Test/Legacy/FooBarTest.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-06 20:03:56 UTC (rev 5437) +++ trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-06 20:39:29 UTC (rev 5438) @@ -60,6 +60,8 @@ RegisterFunction("trim", new AnsiTrimEmulationFunction()); RegisterFunction("mod", new SQLFunctionTemplate(NHibernateUtil.Int32, "((?1) % (?2))")); + + RegisterFunction("iif", new SQLFunctionTemplate(null, "case when ?1 then ?2 else ?3 end")); } public override Schema.IDataBaseSchema GetDataBaseSchema(DbConnection connection) Modified: trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/SQLExceptionConversionTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/SQLExceptionConversionTest.cs 2011-03-06 20:03:56 UTC (rev 5437) +++ trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/SQLExceptionConversionTest.cs 2011-03-06 20:39:29 UTC (rev 5438) @@ -44,6 +44,9 @@ [Test] public void IntegrityViolation() { + if (Dialect is SQLiteDialect) + Assert.Ignore("Example exception converter not implemented."); + //ISQLExceptionConverter converter = Dialect.BuildSQLExceptionConverter(); ISQLExceptionConverter converter = sessions.Settings.SqlExceptionConverter; @@ -107,6 +110,9 @@ [Test] public void BadGrammar() { + if (Dialect is SQLiteDialect) + Assert.Ignore("Example exception converter not implemented."); + //ISQLExceptionConverter converter = Dialect.BuildSQLExceptionConverter(); ISQLExceptionConverter converter = sessions.Settings.SqlExceptionConverter; Modified: trunk/nhibernate/src/NHibernate.Test/Legacy/FooBarTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Legacy/FooBarTest.cs 2011-03-06 20:03:56 UTC (rev 5437) +++ trunk/nhibernate/src/NHibernate.Test/Legacy/FooBarTest.cs 2011-03-06 20:39:29 UTC (rev 5438) @@ -2737,7 +2737,7 @@ IList list; // disable this for dbs with no subselects - if (Dialect.SupportsSubSelects) + if (Dialect.SupportsSubSelects && TestDialect.SupportsOperatorAll) { if (IsClassicParser) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-03-09 05:46:48
|
Revision: 5447 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5447&view=rev Author: patearl Date: 2011-03-09 05:46:42 +0000 (Wed, 09 Mar 2011) Log Message: ----------- Revert two most recent commits. They weren't making any progress. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs trunk/nhibernate/src/NHibernate.Test/TestCase.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-09 04:20:13 UTC (rev 5446) +++ trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-09 05:46:42 UTC (rev 5447) @@ -67,13 +67,6 @@ RegisterFunction("mod", new SQLFunctionTemplate(NHibernateUtil.Int32, "((?1) % (?2))")); RegisterFunction("iif", new SQLFunctionTemplate(null, "case when ?1 then ?2 else ?3 end")); - - // Casting in SQLite is unnecessary since SQLite is essentially typeless. - // String operators can be performed on integers, integer ops on strings, etc. - // For some reason, doing cast('2001-02-03 04:05:06' as datetime) returns 2001. - // In fact, casting to even a type named as a string of garbage returns the same thing. - // Therefore, it's better to avoid the cast function entirely. - RegisterFunction("cast", new SQLFunctionTemplate(null, "(?1)")); } public override Schema.IDataBaseSchema GetDataBaseSchema(DbConnection connection) Modified: trunk/nhibernate/src/NHibernate.Test/TestCase.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/TestCase.cs 2011-03-09 04:20:13 UTC (rev 5446) +++ trunk/nhibernate/src/NHibernate.Test/TestCase.cs 2011-03-09 05:46:42 UTC (rev 5447) @@ -103,8 +103,6 @@ } catch (Exception e) { - // This line just added as a test, since there is no logged output on build server. - Console.WriteLine("Text Fixture Setup Exception: " + e); log.Error("Error while setting up the test fixture", e); throw; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-09 12:25:02
|
Revision: 5448 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5448&view=rev Author: fabiomaulo Date: 2011-03-09 12:24:56 +0000 (Wed, 09 Mar 2011) Log Message: ----------- Fix NH-2565 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs 2011-03-09 05:46:42 UTC (rev 5447) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultPersistEventListener.cs 2011-03-09 12:24:56 UTC (rev 5448) @@ -83,6 +83,15 @@ //TODO: check that entry.getIdentifier().equals(requestedId) object entity = source.PersistenceContext.Unproxy(@event.Entity); + /* NH-2565: the UnProxy may return a "field interceptor proxy". When EntityName is null the session.GetEntityPersister will try to guess it. + * Instead change a session's method I'll try to guess the EntityName here. + * Because I'm using a session's method perhaps could be better if each session's method, which implementation forward to a method having the EntityName as parameter, + * use the BestGuessEntityName directly instead do "70 turns" before call it. + */ + if (@event.EntityName == null) + { + @event.EntityName = source.BestGuessEntityName(entity); + } IEntityPersister persister = source.GetEntityPersister(@event.EntityName, entity); object tempObject; Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-03-09 05:46:42 UTC (rev 5447) +++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-03-09 12:24:56 UTC (rev 5448) @@ -15,6 +15,7 @@ using NHibernate.Engine.Query.Sql; using NHibernate.Event; using NHibernate.Hql; +using NHibernate.Intercept; using NHibernate.Loader.Criteria; using NHibernate.Loader.Custom; using NHibernate.Loader.Custom.Sql; @@ -1043,8 +1044,8 @@ { if (entity.IsProxy()) { - INHibernateProxy proxy = entity as INHibernateProxy; - ILazyInitializer initializer = proxy.HibernateLazyInitializer; + INHibernateProxy proxy = entity as INHibernateProxy; + ILazyInitializer initializer = proxy.HibernateLazyInitializer; // it is possible for this method to be called during flush processing, // so make certain that we do not accidently initialize an uninitialized proxy @@ -1054,6 +1055,12 @@ } entity = initializer.GetImplementation(); } + if (FieldInterceptionHelper.IsInstrumented(entity)) + { + // NH: support of field-interceptor-proxy + IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity); + return interceptor.EntityName; + } EntityEntry entry = persistenceContext.GetEntry(entity); if (entry == null) { Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Domain.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Domain.cs 2011-03-09 12:24:56 UTC (rev 5448) @@ -0,0 +1,17 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2565 +{ + public class Task + { + public virtual Guid Id { get; set; } + public virtual string Description { get; set; } + public virtual TaskActivity Activity { get; set; } + } + + public class TaskActivity + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Fixture.cs 2011-03-09 12:24:56 UTC (rev 5448) @@ -0,0 +1,83 @@ +using System; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2565 +{ + public class Fixture: BugTestCase + { + private class TaskSavedScenario: IDisposable + { + private readonly ISessionFactory factory; + private readonly Guid taskId; + + public TaskSavedScenario(ISessionFactory factory) + { + this.factory = factory; + var activity = new TaskActivity{Name="Say Hello!"}; + var task = new Task { Description = "Nice to do", Activity = activity }; + using (var s = factory.OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Persist(task); + taskId = task.Id; + tx.Commit(); + } + } + + public Guid TaskId + { + get { return taskId; } + } + + public void Dispose() + { + using (var s = factory.OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Delete(s.Get<Task>(taskId)); + tx.Commit(); + } + } + } + + protected override void Configure(Cfg.Configuration configuration) + { + configuration.SetProperty(Cfg.Environment.ProxyFactoryFactoryClass, + typeof(ByteCode.Castle.ProxyFactoryFactory).AssemblyQualifiedName); + } + + [Test] + public void WhenUseLoadThenCanUsePersistToModify() + { + using (var scenario = new TaskSavedScenario(Sfi)) + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + var task = s.Load<Task>(scenario.TaskId); + task.Description = "Could be something nice"; + s.Persist(task); + s.Executing(session => session.Persist(task)).NotThrows(); + tx.Commit(); + } + } + } + + [Test] + public void WhenUseGetThenCanUsePersistToModify() + { + using (var scenario = new TaskSavedScenario(Sfi)) + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + var task = s.Get<Task>(scenario.TaskId); + task.Description = "Could be something nice"; + s.Executing(session => session.Persist(task)).NotThrows(); + tx.Commit(); + } + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2565/Mappings.hbm.xml 2011-03-09 12:24:56 UTC (rev 5448) @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2565"> + + <class name="Task"> + <id name="Id"> + <generator class="guid" /> + </id> + <property name="Description"/> + <many-to-one name="Activity" class="TaskActivity" cascade="all" lazy="no-proxy"/> + </class> + <class name="TaskActivity"> + <id name="Id"> + <generator class="guid" /> + </id> + <property name="Name"/> + </class> +</hibernate-mapping> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-09 05:46:42 UTC (rev 5447) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-09 12:24:56 UTC (rev 5448) @@ -645,6 +645,8 @@ <Compile Include="NHSpecificTest\NH2484\Model.cs" /> <Compile Include="NHSpecificTest\NH2507\Animal.cs" /> <Compile Include="NHSpecificTest\NH2507\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2565\Domain.cs" /> + <Compile Include="NHSpecificTest\NH2565\Fixture.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> @@ -2475,6 +2477,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2565\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\AccessAndCorrectPropertyName\DogMapping.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\AccessAndCorrectPropertyName\PersonMapping.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2507\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-12 19:18:21
|
Revision: 5455 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5455&view=rev Author: fabiomaulo Date: 2011-03-12 19:18:15 +0000 (Sat, 12 Mar 2011) Log Message: ----------- Minor Modified Paths: -------------- trunk/nhibernate/src/NHibernate/NHibernate.nuspec.template trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.Castle.nuspec.template Modified: trunk/nhibernate/src/NHibernate/NHibernate.nuspec.template =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.nuspec.template 2011-03-12 18:58:14 UTC (rev 5454) +++ trunk/nhibernate/src/NHibernate/NHibernate.nuspec.template 2011-03-12 19:18:15 UTC (rev 5455) @@ -4,6 +4,7 @@ <id>NHibernate</id> <version>x.y.z</version> <authors>NHibernate community, Hibernate community</authors> + <summary>NHibernate is a mature, open source object-relational mapper for the .NET framework.</summary> <description> DONT INSTALL IT DIRECTLY Only as reference for others frameworks. Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.Castle.nuspec.template =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.Castle.nuspec.template 2011-03-12 18:58:14 UTC (rev 5454) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.Castle.nuspec.template 2011-03-12 19:18:15 UTC (rev 5455) @@ -4,8 +4,9 @@ <id>NHibernate.Castle</id> <version>x.y.z</version> <authors>NHibernate community, Hibernate community</authors> + <summary>NHibernate with lazy-loading enabled.</summary> <description> - NHibernate is a mature, open source object-relational mapper for the .NET framework. It's actively developed , fully featured and used in thousands of successful projects. + NHibernate is a mature, open source object-relational mapper for the .NET framework. This package enables the ability to use lazy-loading with Castle dynamic-proxy. </description> <language>en-US</language> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-03-13 04:50:27
|
Revision: 5466 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5466&view=rev Author: patearl Date: 2011-03-13 04:50:20 +0000 (Sun, 13 Mar 2011) Log Message: ----------- Implement Left function for SQLite and PostgreSQL. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/PostgreSQLDialect.cs trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1280/NH1280Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/PostgreSQLDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/PostgreSQLDialect.cs 2011-03-13 04:07:31 UTC (rev 5465) +++ trunk/nhibernate/src/NHibernate/Dialect/PostgreSQLDialect.cs 2011-03-13 04:50:20 UTC (rev 5466) @@ -66,6 +66,7 @@ RegisterFunction("substring", new AnsiSubstringFunction()); RegisterFunction("replace", new StandardSQLFunction("replace", NHibernateUtil.String)); + RegisterFunction("left", new SQLFunctionTemplate(NHibernateUtil.String, "substr(?1,1,?2)")); RegisterFunction("mod", new SQLFunctionTemplate(NHibernateUtil.Int32, "((?1) % (?2))")); Modified: trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-13 04:07:31 UTC (rev 5465) +++ trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-13 04:50:20 UTC (rev 5466) @@ -63,6 +63,7 @@ RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "datetime(date(?1))")); RegisterFunction("substring", new StandardSQLFunction("substr", NHibernateUtil.String)); + RegisterFunction("left", new SQLFunctionTemplate(NHibernateUtil.String, "substr(?1,1,?2)")); RegisterFunction("trim", new AnsiTrimEmulationFunction()); RegisterFunction("mod", new SQLFunctionTemplate(NHibernateUtil.Int32, "((?1) % (?2))")); Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1280/NH1280Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1280/NH1280Fixture.cs 2011-03-13 04:07:31 UTC (rev 5465) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1280/NH1280Fixture.cs 2011-03-13 04:50:20 UTC (rev 5466) @@ -224,8 +224,6 @@ [Test] public void SubstringShouldUseAllParameters() { - if(Dialect is PostgreSQLDialect) Assert.Ignore("The dialect {0} doesn't support LEFT function",Dialect.GetType().Name); - using (ISession s = OpenSession()) { using (ITransaction tx = s.BeginTransaction()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-20 17:04:02
|
Revision: 5476 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5476&view=rev Author: fabiomaulo Date: 2011-03-20 17:03:52 +0000 (Sun, 20 Mar 2011) Log Message: ----------- "Initial" upload of embedded DynamicProxy after a little "hands on" Modified Paths: -------------- trunk/nhibernate/src/NHibernate/NHibernate.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-16 14:16:50 UTC (rev 5475) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-20 17:03:52 UTC (rev 5476) @@ -326,6 +326,25 @@ <Compile Include="Properties\PascalCaseMUnderscoreStrategy.cs" /> <Compile Include="Properties\PascalCaseUnderscoreStrategy.cs" /> <Compile Include="Properties\PropertyAccessorFactory.cs" /> + <Compile Include="Proxy\DynamicProxy\DefaultArgumentHandler.cs" /> + <Compile Include="Proxy\DynamicProxy\DefaultMethodEmitter.cs" /> + <Compile Include="Proxy\DynamicProxy\DefaultProxyMethodBuilder.cs" /> + <Compile Include="Proxy\DynamicProxy\HashSetExtensions.cs" /> + <Compile Include="Proxy\DynamicProxy\IArgumentHandler.cs" /> + <Compile Include="Proxy\DynamicProxy\IInterceptor.cs" /> + <Compile Include="Proxy\DynamicProxy\IMethodBodyEmitter.cs" /> + <Compile Include="Proxy\DynamicProxy\InterceptorHandler.cs" /> + <Compile Include="Proxy\DynamicProxy\InvocationHandler.cs" /> + <Compile Include="Proxy\DynamicProxy\InvocationInfo.cs" /> + <Compile Include="Proxy\DynamicProxy\IProxy.cs" /> + <Compile Include="Proxy\DynamicProxy\IProxyCache.cs" /> + <Compile Include="Proxy\DynamicProxy\IProxyMethodBuilder.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyCache.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyCacheEntry.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyDummy.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyFactory.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyImplementor.cs" /> + <Compile Include="Proxy\DynamicProxy\ProxyObjectReference.cs" /> <Compile Include="Proxy\INHibernateProxy.cs" /> <Compile Include="Proxy\IProxyFactory.cs" /> <Compile Include="Proxy\AbstractLazyInitializer.cs" /> Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,74 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + internal class DefaultArgumentHandler : IArgumentHandler + { + #region IArgumentHandler Members + + public void PushArguments(ParameterInfo[] methodParameters, ILGenerator IL, bool isStatic) + { + ParameterInfo[] parameters = methodParameters ?? new ParameterInfo[0]; + int parameterCount = parameters.Length; + + // object[] args = new object[size]; + IL.Emit(OpCodes.Ldc_I4, parameterCount); + IL.Emit(OpCodes.Newarr, typeof (object)); + IL.Emit(OpCodes.Stloc_S, 0); + + if (parameterCount == 0) + { + IL.Emit(OpCodes.Ldloc_S, 0); + return; + } + + // Populate the object array with the list of arguments + int index = 0; + int argumentPosition = 1; + foreach (ParameterInfo param in parameters) + { + System.Type parameterType = param.ParameterType; + // args[N] = argumentN (pseudocode) + IL.Emit(OpCodes.Ldloc_S, 0); + IL.Emit(OpCodes.Ldc_I4, index); + + // Zero out the [out] parameters + if (param.IsOut) + { + IL.Emit(OpCodes.Ldnull); + IL.Emit(OpCodes.Stelem_Ref); + argumentPosition++; + index++; + continue; + } + + IL.Emit(OpCodes.Ldarg, argumentPosition); + + bool isGeneric = parameterType.IsGenericParameter; + + if (parameterType.IsValueType || isGeneric) + { + IL.Emit(OpCodes.Box, parameterType); + } + + IL.Emit(OpCodes.Stelem_Ref); + + index++; + argumentPosition++; + } + IL.Emit(OpCodes.Ldloc_S, 0); + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,240 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + internal class DefaultMethodEmitter : IMethodBodyEmitter + { + private static readonly MethodInfo getInterceptor; + + private static readonly MethodInfo getGenericMethodFromHandle = typeof (MethodBase).GetMethod("GetMethodFromHandle", + BindingFlags.Public | BindingFlags.Static, null, + new[] {typeof (RuntimeMethodHandle), typeof (RuntimeTypeHandle)}, null); + + private static readonly MethodInfo getMethodFromHandle = typeof (MethodBase).GetMethod("GetMethodFromHandle", new[] {typeof (RuntimeMethodHandle)}); + private static readonly MethodInfo getTypeFromHandle = typeof(System.Type).GetMethod("GetTypeFromHandle"); + private static readonly MethodInfo handlerMethod = typeof (IInterceptor).GetMethod("Intercept"); + private static readonly ConstructorInfo infoConstructor; + private static readonly PropertyInfo interceptorProperty = typeof (IProxy).GetProperty("Interceptor"); + + private static readonly ConstructorInfo notImplementedConstructor = typeof(NotImplementedException).GetConstructor(new System.Type[0]); + + private static readonly Dictionary<string, OpCode> stindMap = new Dictionary<string, OpCode>(); + private readonly IArgumentHandler _argumentHandler; + + static DefaultMethodEmitter() + { + getInterceptor = interceptorProperty.GetGetMethod(); + var constructorTypes = new[] + { + typeof (object), typeof (MethodInfo), + typeof (StackTrace), typeof (System.Type[]), typeof (object[]) + }; + + infoConstructor = typeof (InvocationInfo).GetConstructor(constructorTypes); + + + stindMap["Bool&"] = OpCodes.Stind_I1; + stindMap["Int8&"] = OpCodes.Stind_I1; + stindMap["Uint8&"] = OpCodes.Stind_I1; + + stindMap["Int16&"] = OpCodes.Stind_I2; + stindMap["Uint16&"] = OpCodes.Stind_I2; + + stindMap["Uint32&"] = OpCodes.Stind_I4; + stindMap["Int32&"] = OpCodes.Stind_I4; + + stindMap["IntPtr"] = OpCodes.Stind_I4; + stindMap["Uint64&"] = OpCodes.Stind_I8; + stindMap["Int64&"] = OpCodes.Stind_I8; + stindMap["Float32&"] = OpCodes.Stind_R4; + stindMap["Float64&"] = OpCodes.Stind_R8; + } + + public DefaultMethodEmitter() : this(new DefaultArgumentHandler()) {} + + public DefaultMethodEmitter(IArgumentHandler argumentHandler) + { + _argumentHandler = argumentHandler; + } + + #region IMethodBodyEmitter Members + + public void EmitMethodBody(ILGenerator IL, MethodInfo method, FieldInfo field) + { + ParameterInfo[] parameters = method.GetParameters(); + IL.DeclareLocal(typeof (object[])); + IL.DeclareLocal(typeof (InvocationInfo)); + IL.DeclareLocal(typeof(System.Type[])); + + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Callvirt, getInterceptor); + + // if (interceptor == null) + // throw new NullReferenceException(); + + Label skipThrow = IL.DefineLabel(); + + IL.Emit(OpCodes.Dup); + IL.Emit(OpCodes.Ldnull); + IL.Emit(OpCodes.Bne_Un, skipThrow); + + IL.Emit(OpCodes.Newobj, notImplementedConstructor); + IL.Emit(OpCodes.Throw); + + IL.MarkLabel(skipThrow); + // Push the 'this' pointer onto the stack + IL.Emit(OpCodes.Ldarg_0); + + // Push the MethodInfo onto the stack + System.Type declaringType = method.DeclaringType; + + IL.Emit(OpCodes.Ldtoken, method); + if (declaringType.IsGenericType) + { + IL.Emit(OpCodes.Ldtoken, declaringType); + IL.Emit(OpCodes.Call, getGenericMethodFromHandle); + } + else + { + IL.Emit(OpCodes.Call, getMethodFromHandle); + } + + IL.Emit(OpCodes.Castclass, typeof (MethodInfo)); + + PushStackTrace(IL); + PushGenericArguments(method, IL); + _argumentHandler.PushArguments(parameters, IL, false); + + // InvocationInfo info = new InvocationInfo(...); + + IL.Emit(OpCodes.Newobj, infoConstructor); + IL.Emit(OpCodes.Stloc_1); + IL.Emit(OpCodes.Ldloc_1); + IL.Emit(OpCodes.Callvirt, handlerMethod); + + SaveRefArguments(IL, parameters); + PackageReturnType(method, IL); + + IL.Emit(OpCodes.Ret); + } + + #endregion + + private static void SaveRefArguments(ILGenerator IL, ParameterInfo[] parameters) + { + // Save the arguments returned from the handler method + MethodInfo getArguments = typeof (InvocationInfo).GetMethod("get_Arguments"); + IL.Emit(OpCodes.Ldloc_1); + IL.Emit(OpCodes.Call, getArguments); + IL.Emit(OpCodes.Stloc_0); + + foreach (ParameterInfo param in parameters) + { + string typeName = param.ParameterType.Name; + + bool isRef = param.ParameterType.IsByRef && typeName.EndsWith("&"); + if (!isRef) + { + continue; + } + + // Load the destination address + IL.Emit(OpCodes.Ldarg, param.Position + 1); + + // Load the argument value + IL.Emit(OpCodes.Ldloc_0); + IL.Emit(OpCodes.Ldc_I4, param.Position); + IL.Emit(OpCodes.Ldelem_Ref); + + typeName = typeName.Replace("&", ""); + System.Type unboxedType = System.Type.GetType(typeName); + + IL.Emit(OpCodes.Unbox_Any, unboxedType); + + OpCode stind = GetStindInstruction(param.ParameterType); + IL.Emit(stind); + } + } + + private static OpCode GetStindInstruction(System.Type parameterType) + { + if (parameterType.IsClass && !parameterType.Name.EndsWith("&")) + { + return OpCodes.Stind_Ref; + } + + + string typeName = parameterType.Name; + + if (!stindMap.ContainsKey(typeName) && parameterType.IsByRef) + { + return OpCodes.Stind_Ref; + } + + Debug.Assert(stindMap.ContainsKey(typeName)); + OpCode result = stindMap[typeName]; + + return result; + } + + private void PushStackTrace(ILGenerator IL) + { + // NOTE: The stack trace has been disabled for performance reasons + IL.Emit(OpCodes.Ldnull); + } + + private void PushGenericArguments(MethodInfo method, ILGenerator IL) + { + System.Type[] typeParameters = method.GetGenericArguments(); + + // If this is a generic method, we need to store + // the generic method arguments + int genericTypeCount = typeParameters.Length; + + // Type[] genericTypeArgs = new Type[genericTypeCount]; + IL.Emit(OpCodes.Ldc_I4, genericTypeCount); + IL.Emit(OpCodes.Newarr, typeof(System.Type)); + + if (genericTypeCount == 0) + { + return; + } + + for (int index = 0; index < genericTypeCount; index++) + { + System.Type currentType = typeParameters[index]; + + IL.Emit(OpCodes.Dup); + IL.Emit(OpCodes.Ldc_I4, index); + IL.Emit(OpCodes.Ldtoken, currentType); + IL.Emit(OpCodes.Call, getTypeFromHandle); + IL.Emit(OpCodes.Stelem_Ref); + } + } + + private void PackageReturnType(MethodInfo method, ILGenerator IL) + { + System.Type returnType = method.ReturnType; + // Unbox the return value if necessary + if (returnType == typeof (void)) + { + IL.Emit(OpCodes.Pop); + return; + } + + IL.Emit(OpCodes.Unbox_Any, returnType); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,67 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + internal class DefaultyProxyMethodBuilder : IProxyMethodBuilder + { + public DefaultyProxyMethodBuilder() : this(new DefaultMethodEmitter()) {} + + public DefaultyProxyMethodBuilder(IMethodBodyEmitter emitter) + { + if (emitter == null) + { + throw new ArgumentNullException("emitter"); + } + MethodBodyEmitter = emitter; + } + + public IMethodBodyEmitter MethodBodyEmitter { get; private set; } + + #region IProxyMethodBuilder Members + + public void CreateProxiedMethod(FieldInfo field, MethodInfo method, TypeBuilder typeBuilder) + { + const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | + MethodAttributes.Virtual; + ParameterInfo[] parameters = method.GetParameters(); + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes, + CallingConventions.HasThis, method.ReturnType, + parameters.Select(param => param.ParameterType).ToArray()); + + System.Type[] typeArgs = method.GetGenericArguments(); + + if (typeArgs.Length > 0) + { + var typeNames = new List<string>(); + + for (int index = 0; index < typeArgs.Length; index++) + { + typeNames.Add(string.Format("T{0}", index)); + } + + methodBuilder.DefineGenericParameters(typeNames.ToArray()); + } + + ILGenerator IL = methodBuilder.GetILGenerator(); + + Debug.Assert(MethodBodyEmitter != null); + MethodBodyEmitter.EmitMethodBody(IL, method, field); + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace NHibernate.Proxy.DynamicProxy +{ + public static class HashSetExtensions + { + public static HashSet<T> Merge<T>(this HashSet<T> source, IEnumerable<T> toMerge) + { + foreach (T item in toMerge) + { + source.Add(item); + } + return source; + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,18 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IArgumentHandler + { + void PushArguments(ParameterInfo[] parameters, ILGenerator IL, bool isStatic); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,15 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IInterceptor + { + object Intercept(InvocationInfo info); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,18 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IMethodBodyEmitter + { + void EmitMethodBody(ILGenerator IL, MethodInfo method, FieldInfo field); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,15 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IProxy + { + IInterceptor Interceptor { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,19 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IProxyCache + { + bool Contains(System.Type baseType, params System.Type[] baseInterfaces); + System.Type GetProxyType(System.Type baseType, params System.Type[] baseInterfaces); + void StoreProxyType(System.Type result, System.Type baseType, params System.Type[] baseInterfaces); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,18 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + public interface IProxyMethodBuilder + { + void CreateProxiedMethod(FieldInfo field, MethodInfo method, TypeBuilder typeBuilder); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,17 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Diagnostics; +using System.Reflection; + +namespace NHibernate.Proxy.DynamicProxy +{ + public delegate object InterceptorHandler(object proxy, MethodInfo targetMethod, + StackTrace trace, System.Type[] genericTypeArgs, object[] args); +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,12 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +namespace NHibernate.Proxy.DynamicProxy +{ + public delegate object InvocationHandler(InvocationInfo info); +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,109 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Text; + +namespace NHibernate.Proxy.DynamicProxy +{ + public class InvocationInfo + { + private readonly object[] args; + private readonly object proxy; + private readonly MethodInfo targetMethod; + private readonly StackTrace trace; + private readonly System.Type[] typeArgs; + + public InvocationInfo(object proxy, MethodInfo targetMethod, + StackTrace trace, System.Type[] genericTypeArgs, object[] args) + { + this.proxy = proxy; + this.targetMethod = targetMethod; + typeArgs = genericTypeArgs; + this.args = args; + this.trace = trace; + } + + public object Target + { + get { return proxy; } + } + + public MethodInfo TargetMethod + { + get { return targetMethod; } + } + + public StackTrace StackTrace + { + get { return trace; } + } + + public System.Type[] TypeArguments + { + get { return typeArgs; } + } + + public object[] Arguments + { + get { return args; } + } + + public void SetArgument(int position, object arg) + { + args[position] = arg; + } + + public override string ToString() + { + var builder = new StringBuilder(); + builder.AppendFormat("Target Method:{0,30:G}\n", GetMethodName(targetMethod)); + builder.AppendLine("Arguments:"); + + foreach (ParameterInfo info in targetMethod.GetParameters()) + { + object currentArgument = args[info.Position]; + if (currentArgument == null) + { + currentArgument = "(null)"; + } + builder.AppendFormat("\t{0,10:G}: {1}\n", info.Name, currentArgument); + } + builder.AppendLine(); + + return builder.ToString(); + } + + private string GetMethodName(MethodInfo method) + { + var builder = new StringBuilder(512); + builder.AppendFormat("{0}.{1}", method.DeclaringType.Name, method.Name); + builder.Append("("); + + ParameterInfo[] parameters = method.GetParameters(); + int parameterCount = parameters.Length; + + int index = 0; + foreach (ParameterInfo param in parameters) + { + index++; + builder.AppendFormat("{0} {1}", param.ParameterType.Name, param.Name); + + if (index < parameterCount) + { + builder.Append(", "); + } + } + builder.Append(")"); + + return builder.ToString(); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,52 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; + +namespace NHibernate.Proxy.DynamicProxy +{ + public class ProxyCache : IProxyCache + { + private readonly Dictionary<ProxyCacheEntry, System.Type> cache = new Dictionary<ProxyCacheEntry, System.Type>(); + private readonly object syncObject = new object(); + + #region IProxyCache Members + + public bool Contains(System.Type baseType, params System.Type[] baseInterfaces) + { + if (baseType == null) + { + return false; + } + + var entry = new ProxyCacheEntry(baseType, baseInterfaces); + return cache.ContainsKey(entry); + } + + public System.Type GetProxyType(System.Type baseType, params System.Type[] baseInterfaces) + { + lock (syncObject) + { + var entry = new ProxyCacheEntry(baseType, baseInterfaces); + return cache[entry]; + } + } + + public void StoreProxyType(System.Type result, System.Type baseType, params System.Type[] baseInterfaces) + { + lock (syncObject) + { + var entry = new ProxyCacheEntry(baseType, baseInterfaces); + cache[entry] = result; + } + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,62 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; + +namespace NHibernate.Proxy.DynamicProxy +{ + [Serializable] + public class ProxyCacheEntry + { + private readonly int hashCode; + + public ProxyCacheEntry(System.Type baseType, System.Type[] interfaces) + { + if (baseType == null) + { + throw new ArgumentNullException("baseType"); + } + BaseType = baseType; + Interfaces = interfaces ?? new System.Type[0]; + + if (Interfaces.Length == 0) + { + hashCode = baseType.GetHashCode(); + return; + } + + // duplicated type exclusion + var set = new HashSet<System.Type>(Interfaces) { baseType }; + hashCode = 59; + foreach (System.Type type in set) + { + hashCode ^= type.GetHashCode(); + } + } + + public System.Type BaseType { get; private set; } + public System.Type[] Interfaces { get; private set; } + + public override bool Equals(object obj) + { + var that = obj as ProxyCacheEntry; + if (ReferenceEquals(null, that)) + { + return false; + } + + return hashCode == that.GetHashCode(); + } + + public override int GetHashCode() + { + return hashCode; + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,15 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +namespace NHibernate.Proxy.DynamicProxy +{ + public class ProxyDummy + { + /* No Implementation */ + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,306 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.Serialization; + +namespace NHibernate.Proxy.DynamicProxy +{ + public sealed class ProxyFactory + { + private static readonly ConstructorInfo baseConstructor = typeof(object).GetConstructor(new System.Type[0]); + private static readonly MethodInfo getTypeFromHandle = typeof(System.Type).GetMethod("GetTypeFromHandle"); + + private static readonly MethodInfo getValue = typeof (SerializationInfo).GetMethod("GetValue", BindingFlags.Public | BindingFlags.Instance, null, + new[] { typeof(string), typeof(System.Type) }, null); + + private static readonly MethodInfo setType = typeof(SerializationInfo).GetMethod("SetType", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(System.Type) }, null); + + private static readonly MethodInfo addValue = typeof (SerializationInfo).GetMethod("AddValue", BindingFlags.Public | BindingFlags.Instance, null, + new[] {typeof (string), typeof (object)}, null); + + public ProxyFactory() + : this(new DefaultyProxyMethodBuilder()) {} + + public ProxyFactory(IProxyMethodBuilder proxyMethodBuilder) + { + if (proxyMethodBuilder == null) + { + throw new ArgumentNullException("proxyMethodBuilder"); + } + ProxyMethodBuilder = proxyMethodBuilder; + Cache = new ProxyCache(); + } + + public IProxyCache Cache { get; private set; } + + public IProxyMethodBuilder ProxyMethodBuilder { get; private set; } + + public object CreateProxy(System.Type instanceType, IInterceptor interceptor, params System.Type[] baseInterfaces) + { + System.Type proxyType = CreateProxyType(instanceType, baseInterfaces); + object result = Activator.CreateInstance(proxyType); + var proxy = (IProxy) result; + proxy.Interceptor = interceptor; + + return result; + } + + public System.Type CreateProxyType(System.Type baseType, params System.Type[] interfaces) + { + System.Type[] baseInterfaces = ReferenceEquals(null, interfaces) ? new System.Type[0] : interfaces.Where(t => t != null).ToArray(); + // Reuse the previous results, if possible + if (Cache.Contains(baseType, baseInterfaces)) + { + return Cache.GetProxyType(baseType, baseInterfaces); + } + + System.Type result = CreateUncachedProxyType(baseType, baseInterfaces); + + // Cache the proxy type + if (result != null && Cache != null) + { + Cache.StoreProxyType(result, baseType, baseInterfaces); + } + + return result; + } + + private System.Type CreateUncachedProxyType(System.Type baseType, System.Type[] baseInterfaces) + { + AppDomain currentDomain = AppDomain.CurrentDomain; + string typeName = string.Format("{0}Proxy", baseType.Name); + string assemblyName = string.Format("{0}Assembly", typeName); + string moduleName = string.Format("{0}Module", typeName); + + var name = new AssemblyName(assemblyName); +#if DEBUG + AssemblyBuilderAccess access = AssemblyBuilderAccess.RunAndSave; +#else + AssemblyBuilderAccess access = AssemblyBuilderAccess.Run; +#endif + AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name, access); + +#if DEBUG + ModuleBuilder moduleBuilder = + assemblyBuilder.DefineDynamicModule(moduleName, string.Format("{0}.mod", moduleName), true); +#else + ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName); +#endif + + TypeAttributes typeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class | + TypeAttributes.Public | TypeAttributes.BeforeFieldInit; + + var interfaces = new HashSet<System.Type>(); + interfaces.Merge(baseInterfaces); + + // Use the proxy dummy as the base type + // since we're not inheriting from any class type + System.Type parentType = baseType; + if (baseType.IsInterface) + { + parentType = typeof (ProxyDummy); + interfaces.Add(baseType); + } + + // Add any inherited interfaces + System.Type[] computedInterfaces = interfaces.ToArray(); + foreach (System.Type interfaceType in computedInterfaces) + { + interfaces.Merge(GetInterfaces(interfaceType)); + } + + // Add the ISerializable interface so that it can be implemented + interfaces.Add(typeof (ISerializable)); + + TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, parentType, interfaces.ToArray()); + + ConstructorBuilder defaultConstructor = DefineConstructor(typeBuilder); + + // Implement IProxy + var implementor = new ProxyImplementor(); + implementor.ImplementProxy(typeBuilder); + + FieldInfo interceptorField = implementor.InterceptorField; + + // Provide a custom implementation of ISerializable + // instead of redirecting it back to the interceptor + foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable))) + { + ProxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder); + } + + // Make the proxy serializable + AddSerializationSupport(baseType, baseInterfaces, typeBuilder, interceptorField, defaultConstructor); + System.Type proxyType = typeBuilder.CreateType(); + +#if DEBUG_PROXY_OUTPUT + assemblyBuilder.Save("generatedAssembly.dll"); +#endif + return proxyType; + } + + private IEnumerable<System.Type> GetInterfaces(System.Type currentType) + { + return GetAllInterfaces(currentType); + } + + private IEnumerable<System.Type> GetAllInterfaces(System.Type currentType) + { + System.Type[] interfaces = currentType.GetInterfaces(); + + foreach (System.Type current in interfaces) + { + yield return current; + foreach (System.Type @interface in GetAllInterfaces(current)) + { + yield return @interface; + } + } + } + + private IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces) + { + const BindingFlags candidateMethodsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + return + type.GetMethods(candidateMethodsBindingFlags) + .Where(method => IsProxiable(method)) + .Concat(interfaces.SelectMany(interfaceType => interfaceType.GetMethods())).Distinct(); + } + + private bool IsProxiable(MethodInfo method) + { + return (((method.IsPublic || method.IsFamily || method.IsAssembly || method.IsFamilyOrAssembly) + && (method.IsVirtual || method.IsAbstract)) + && (method.DeclaringType != typeof(MarshalByRefObject))) + && (method.DeclaringType != typeof(object) || !"finalize".Equals(method.Name.ToLowerInvariant())); + } + + private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder) + { + const MethodAttributes constructorAttributes = MethodAttributes.Public | + MethodAttributes.HideBySig | MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName; + + ConstructorBuilder constructor = + typeBuilder.DefineConstructor(constructorAttributes, CallingConventions.Standard, new System.Type[0]); + + ILGenerator IL = constructor.GetILGenerator(); + + constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed); + + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Call, baseConstructor); + IL.Emit(OpCodes.Ret); + + return constructor; + } + + private static void ImplementGetObjectData(System.Type baseType, System.Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField) + { + const MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | + MethodAttributes.Virtual; + var parameterTypes = new[] {typeof (SerializationInfo), typeof (StreamingContext)}; + + MethodBuilder methodBuilder = + typeBuilder.DefineMethod("GetObjectData", attributes, typeof (void), parameterTypes); + + ILGenerator IL = methodBuilder.GetILGenerator(); + //LocalBuilder proxyBaseType = IL.DeclareLocal(typeof(Type)); + + // info.SetType(typeof(ProxyObjectReference)); + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldtoken, typeof (ProxyObjectReference)); + IL.Emit(OpCodes.Call, getTypeFromHandle); + IL.Emit(OpCodes.Callvirt, setType); + + // info.AddValue("__interceptor", __interceptor); + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldstr, "__interceptor"); + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Ldfld, interceptorField); + IL.Emit(OpCodes.Callvirt, addValue); + + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldstr, "__baseType"); + IL.Emit(OpCodes.Ldstr, baseType.AssemblyQualifiedName); + IL.Emit(OpCodes.Callvirt, addValue); + + int baseInterfaceCount = baseInterfaces.Length; + + // Save the number of base interfaces + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldstr, "__baseInterfaceCount"); + IL.Emit(OpCodes.Ldc_I4, baseInterfaceCount); + IL.Emit(OpCodes.Box, typeof (Int32)); + IL.Emit(OpCodes.Callvirt, addValue); + + int index = 0; + foreach (System.Type baseInterface in baseInterfaces) + { + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldstr, string.Format("__baseInterface{0}", index++)); + IL.Emit(OpCodes.Ldstr, baseInterface.AssemblyQualifiedName); + IL.Emit(OpCodes.Callvirt, addValue); + } + + IL.Emit(OpCodes.Ret); + } + + private static void DefineSerializationConstructor(TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor) + { + const MethodAttributes constructorAttributes = MethodAttributes.Public | + MethodAttributes.HideBySig | MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName; + + var parameterTypes = new[] {typeof (SerializationInfo), typeof (StreamingContext)}; + ConstructorBuilder constructor = typeBuilder.DefineConstructor(constructorAttributes, + CallingConventions.Standard, parameterTypes); + + ILGenerator IL = constructor.GetILGenerator(); + + LocalBuilder interceptorType = IL.DeclareLocal(typeof(System.Type)); + //LocalBuilder interceptor = IL.DeclareLocal(typeof(IInterceptor)); + + constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed); + + + IL.Emit(OpCodes.Ldtoken, typeof (IInterceptor)); + IL.Emit(OpCodes.Call, getTypeFromHandle); + IL.Emit(OpCodes.Stloc, interceptorType); + + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Call, defaultConstructor); + + // __interceptor = (IInterceptor)info.GetValue("__interceptor", typeof(IInterceptor)); + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Ldstr, "__interceptor"); + IL.Emit(OpCodes.Ldloc, interceptorType); + IL.Emit(OpCodes.Callvirt, getValue); + IL.Emit(OpCodes.Castclass, typeof (IInterceptor)); + IL.Emit(OpCodes.Stfld, interceptorField); + + IL.Emit(OpCodes.Ret); + } + + private static void AddSerializationSupport(System.Type baseType, System.Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor) + { + ConstructorInfo serializableConstructor = typeof(SerializableAttribute).GetConstructor(new System.Type[0]); + var customAttributeBuilder = new CustomAttributeBuilder(serializableConstructor, new object[0]); + typeBuilder.SetCustomAttribute(customAttributeBuilder); + + DefineSerializationConstructor(typeBuilder, interceptorField, defaultConstructor); + ImplementGetObjectData(baseType, baseInterfaces, typeBuilder, interceptorField); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,64 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace NHibernate.Proxy.DynamicProxy +{ + internal class ProxyImplementor + { + private const MethodAttributes InterceptorMethodsAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | + MethodAttributes.SpecialName | MethodAttributes.NewSlot | + MethodAttributes.Virtual; + + private FieldBuilder field; + + public FieldBuilder InterceptorField + { + get { return field; } + } + + public void ImplementProxy(TypeBuilder typeBuilder) + { + // Implement the IProxy interface + typeBuilder.AddInterfaceImplementation(typeof (IProxy)); + + field = typeBuilder.DefineField("__interceptor", typeof (IInterceptor), FieldAttributes.Private); + + // Implement the getter + MethodBuilder getterMethod = typeBuilder.DefineMethod("get_Interceptor", InterceptorMethodsAttributes, CallingConventions.HasThis, typeof(IInterceptor), new System.Type[0]); + getterMethod.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL); + + ILGenerator IL = getterMethod.GetILGenerator(); + + // This is equivalent to: + // get { return __interceptor; + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Ldfld, field); + IL.Emit(OpCodes.Ret); + + // Implement the setter + MethodBuilder setterMethod = typeBuilder.DefineMethod("set_Interceptor", InterceptorMethodsAttributes, CallingConventions.HasThis, typeof (void), new[] {typeof (IInterceptor)}); + + setterMethod.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL); + IL = setterMethod.GetILGenerator(); + IL.Emit(OpCodes.Ldarg_0); + IL.Emit(OpCodes.Ldarg_1); + IL.Emit(OpCodes.Stfld, field); + IL.Emit(OpCodes.Ret); + + MethodInfo originalSetter = typeof (IProxy).GetMethod("set_Interceptor"); + MethodInfo originalGetter = typeof (IProxy).GetMethod("get_Interceptor"); + + typeBuilder.DefineMethodOverride(setterMethod, originalSetter); + typeBuilder.DefineMethodOverride(getterMethod, originalGetter); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs 2011-03-20 17:03:52 UTC (rev 5476) @@ -0,0 +1,63 @@ +#region Credits + +// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project. +// The license is the same of NHibernate license (LGPL Version 2.1, February 1999). +// The source was then modified to be the default DynamicProxy of NHibernate project. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace NHibernate.Proxy.DynamicProxy +{ + [Serializable] + public class ProxyObjectReference : IObjectReference, ISerializable + { + private readonly System.Type _baseType; + private readonly IProxy _proxy; + + protected ProxyObjectReference(SerializationInfo info, StreamingContext context) + { + // Deserialize the base type using its assembly qualified name + string qualifiedName = info.GetString("__baseType"); + _baseType = System.Type.GetType(qualifiedName, true, false); + + // Rebuild the list of interfaces + var interfaceList = new List<System.Type>(); + int interfaceCount = info.GetInt32("__baseInterfaceCount"); + for (int i = 0; i < interfaceCount; i++) + { + string keyName = string.Format("__baseInterface{0}", i); + string currentQualifiedName = info.GetString(keyName); + System.Type interfaceType = System.Type.GetType(currentQualifiedName, true, false); + + interfaceList.Add(interfaceType); + } + + // Reconstruct the proxy + var factory = new ProxyFactory(); + System.Type proxyType = factory.CreateProxyType(_baseType, interfaceList.ToArray()); + + // Initialize the proxy with the deserialized data + var args = new object[] {info, context}; + _proxy = (IProxy) Activator.CreateInstance(proxyType, args); + } + + #region IObjectReference Members + + public object GetRealObject(StreamingContext context) + { + return _proxy; + } + + #endregion + + #region ISerializable Members + + public void GetObjectData(SerializationInfo info, StreamingContext context) {} + + #endregion + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-20 17:31:20
|
Revision: 5477 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5477&view=rev Author: fabiomaulo Date: 2011-03-20 17:31:14 +0000 (Sun, 20 Mar 2011) Log Message: ----------- Artifacts for default bytecode provider Modified Paths: -------------- trunk/nhibernate/src/NHibernate/NHibernate.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Bytecode/DefaultProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate/Intercept/DefaultDynamicLazyFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Proxy/DefaultLazyInitializer.cs trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs Added: trunk/nhibernate/src/NHibernate/Bytecode/DefaultProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Bytecode/DefaultProxyFactoryFactory.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Bytecode/DefaultProxyFactoryFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) @@ -0,0 +1,31 @@ +using NHibernate.Proxy; + +namespace NHibernate.Bytecode +{ + public class DefaultProxyFactoryFactory : IProxyFactoryFactory + { + #region IProxyFactoryFactory Members + + public IProxyFactory BuildProxyFactory() + { + return new DefaultProxyFactory(); + } + + public IProxyValidator ProxyValidator + { + get { return new DynProxyTypeValidator(); } + } + + public bool IsInstrumented(System.Type entityClass) + { + return true; + } + + public bool IsProxy(object entity) + { + return entity is INHibernateProxy; + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Intercept/DefaultDynamicLazyFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultDynamicLazyFieldInterceptor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultDynamicLazyFieldInterceptor.cs 2011-03-20 17:31:14 UTC (rev 5477) @@ -0,0 +1,64 @@ +using System; +using NHibernate.Proxy.DynamicProxy; +using NHibernate.Util; + +namespace NHibernate.Intercept +{ + public class DefaultDynamicLazyFieldInterceptor : IFieldInterceptorAccessor, Proxy.DynamicProxy.IInterceptor + { + public DefaultDynamicLazyFieldInterceptor(object targetInstance) + { + if (targetInstance == null) + { + throw new ArgumentNullException("targetInstance"); + } + TargetInstance = targetInstance; + } + + public IFieldInterceptor FieldInterceptor { get; set; } + public object TargetInstance { get; private set; } + + public object Intercept(InvocationInfo info) + { + var methodName = info.TargetMethod.Name; + if (FieldInterceptor != null) + { + if (ReflectHelper.IsPropertyGet(info.TargetMethod)) + { + if("get_FieldInterceptor".Equals(methodName)) + { + return FieldInterceptor; + } + object propValue = info.TargetMethod.Invoke(TargetInstance, info.Arguments); + + var result = FieldInterceptor.Intercept(info.Target, ReflectHelper.GetPropertyName(info.TargetMethod), propValue); + + if (result != AbstractFieldInterceptor.InvokeImplementation) + { + return result; + } + } + else if (ReflectHelper.IsPropertySet(info.TargetMethod)) + { + if ("set_FieldInterceptor".Equals(methodName)) + { + FieldInterceptor = (IFieldInterceptor)info.Arguments[0]; + return null; + } + FieldInterceptor.MarkDirty(); + FieldInterceptor.Intercept(info.Target, ReflectHelper.GetPropertyName(info.TargetMethod), info.Arguments[0]); + } + } + else + { + if ("set_FieldInterceptor".Equals(methodName)) + { + FieldInterceptor = (IFieldInterceptor)info.Arguments[0]; + return null; + } + } + + return info.TargetMethod.Invoke(TargetInstance, info.Arguments); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-20 17:03:52 UTC (rev 5476) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-20 17:31:14 UTC (rev 5477) @@ -91,6 +91,7 @@ <Compile Include="ADOException.cs" /> <Compile Include="AssemblyInfo.cs" /> <Compile Include="AssertionFailure.cs" /> + <Compile Include="Bytecode\DefaultProxyFactoryFactory.cs" /> <Compile Include="Cache\Access\ISoftLock.cs" /> <Compile Include="Cache\CachedItem.cs" /> <Compile Include="Cache\CacheException.cs" /> @@ -252,6 +253,7 @@ <Compile Include="Impl\SqlQueryImpl.cs" /> <Compile Include="Engine\Status.cs" /> <Compile Include="InstantiationException.cs" /> + <Compile Include="Intercept\DefaultDynamicLazyFieldInterceptor.cs" /> <Compile Include="IQuery.cs" /> <Compile Include="ISession.cs" /> <Compile Include="ISessionFactory.cs" /> @@ -326,6 +328,8 @@ <Compile Include="Properties\PascalCaseMUnderscoreStrategy.cs" /> <Compile Include="Properties\PascalCaseUnderscoreStrategy.cs" /> <Compile Include="Properties\PropertyAccessorFactory.cs" /> + <Compile Include="Proxy\DefaultLazyInitializer.cs" /> + <Compile Include="Proxy\DefaultProxyFactory.cs" /> <Compile Include="Proxy\DynamicProxy\DefaultArgumentHandler.cs" /> <Compile Include="Proxy\DynamicProxy\DefaultMethodEmitter.cs" /> <Compile Include="Proxy\DynamicProxy\DefaultProxyMethodBuilder.cs" /> Added: trunk/nhibernate/src/NHibernate/Proxy/DefaultLazyInitializer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DefaultLazyInitializer.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DefaultLazyInitializer.cs 2011-03-20 17:31:14 UTC (rev 5477) @@ -0,0 +1,48 @@ +using System; +using System.Reflection; +using NHibernate.Engine; +using NHibernate.Proxy.DynamicProxy; +using NHibernate.Proxy.Poco; +using NHibernate.Type; + +namespace NHibernate.Proxy +{ + public class DefaultLazyInitializer : BasicLazyInitializer, DynamicProxy.IInterceptor + { + private static readonly MethodInfo exceptionInternalPreserveStackTrace = + typeof (Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); + + public DefaultLazyInitializer(string entityName, System.Type persistentClass, object id, MethodInfo getIdentifierMethod, + MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType, + ISessionImplementor session) + : base(entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session) {} + + #region Implementation of IInterceptor + + public object Intercept(InvocationInfo info) + { + object returnValue; + try + { + returnValue = base.Invoke(info.TargetMethod, info.Arguments, info.Target); + + // Avoid invoking the actual implementation, if possible + if (returnValue != InvokeImplementation) + { + return returnValue; + } + + returnValue = info.TargetMethod.Invoke(GetImplementation(), info.Arguments); + } + catch (TargetInvocationException ex) + { + exceptionInternalPreserveStackTrace.Invoke(ex.InnerException, new Object[] {}); + throw ex.InnerException; + } + + return returnValue; + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) @@ -0,0 +1,40 @@ +using System; +using NHibernate.Engine; +using NHibernate.Intercept; +using NHibernate.Proxy.DynamicProxy; + +namespace NHibernate.Proxy +{ + public class DefaultProxyFactory : AbstractProxyFactory + { + private static readonly ProxyFactory factory = new ProxyFactory(); + protected static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (DefaultProxyFactory)); + + public override INHibernateProxy GetProxy(object id, ISessionImplementor session) + { + try + { + var initializer = new DefaultLazyInitializer(EntityName, PersistentClass, id, GetIdentifierMethod, SetIdentifierMethod, + ComponentIdType, session); + + object proxyInstance = IsClassProxy + ? factory.CreateProxy(PersistentClass, initializer, Interfaces) + : factory.CreateProxy(Interfaces[0], initializer, Interfaces); + + return (INHibernateProxy) proxyInstance; + } + catch (Exception ex) + { + log.Error("Creating a proxy instance failed", ex); + throw new HibernateException("Creating a proxy instance failed", ex); + } + } + + public override object GetFieldInterceptionProxy() + { + object targetInstance = Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(PersistentClass, true); + var interceptor = new DefaultDynamicLazyFieldInterceptor(targetInstance); + return factory.CreateProxy(PersistentClass, interceptor, new[] { typeof(IFieldInterceptorAccessor) }); + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-20 17:43:32
|
Revision: 5478 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5478&view=rev Author: fabiomaulo Date: 2011-03-20 17:43:25 +0000 (Sun, 20 Mar 2011) Log Message: ----------- Changed IProxyFactory to get the instance to wrap, for proxy "field-interceptor" Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs Modified: trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -44,7 +44,7 @@ public abstract INHibernateProxy GetProxy(object id, ISessionImplementor session); - public virtual object GetFieldInterceptionProxy() + public virtual object GetFieldInterceptionProxy(object instanceToWrap) { throw new NotSupportedException(); } Modified: trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate/Proxy/DefaultProxyFactory.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -30,10 +30,9 @@ } } - public override object GetFieldInterceptionProxy() + public override object GetFieldInterceptionProxy(object instanceToWrap) { - object targetInstance = Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(PersistentClass, true); - var interceptor = new DefaultDynamicLazyFieldInterceptor(targetInstance); + var interceptor = new DefaultDynamicLazyFieldInterceptor(instanceToWrap); return factory.CreateProxy(PersistentClass, interceptor, new[] { typeof(IFieldInterceptorAccessor) }); } } Modified: trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -49,6 +49,6 @@ /// <exception cref="HibernateException">Indicates problems generating requested proxy.</exception> INHibernateProxy GetProxy(object id, ISessionImplementor session); - object GetFieldInterceptionProxy(); + object GetFieldInterceptionProxy(object instanceToWrap); } } Modified: trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -24,7 +24,7 @@ return new MapProxy(new MapLazyInitializer(entityName, id, session)); } - public object GetFieldInterceptionProxy() + public object GetFieldInterceptionProxy(object getInstance) { throw new NotSupportedException(); } Modified: trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -90,8 +90,13 @@ } if (generateFieldInterceptionProxy) { - return proxyFactory.GetFieldInterceptionProxy(); + return proxyFactory.GetFieldInterceptionProxy(GetInstance()); } + return GetInstance(); + } + + private object GetInstance() + { if (optimizer != null) { return optimizer.CreateInstance(); Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -44,7 +44,7 @@ } - public override object GetFieldInterceptionProxy() + public override object GetFieldInterceptionProxy(object instanceToWrap) { var proxyGenerationOptions = new ProxyGenerationOptions(); var interceptor = new LazyFieldInterceptor(); Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs 2011-03-20 17:31:14 UTC (rev 5477) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/LazyFieldInterceptorSerializable.cs 2011-03-20 17:43:25 UTC (rev 5478) @@ -26,7 +26,7 @@ var pf = new ProxyFactory(); var propertyInfo = typeof(MyClass).GetProperty("Id"); pf.PostInstantiate("MyClass", typeof(MyClass), new HashedSet<System.Type>(), propertyInfo.GetGetMethod(), propertyInfo.GetSetMethod(), null); - var fieldInterceptionProxy = (IFieldInterceptorAccessor)pf.GetFieldInterceptionProxy(); + var fieldInterceptionProxy = (IFieldInterceptorAccessor)pf.GetFieldInterceptionProxy(new MyClass()); fieldInterceptionProxy.FieldInterceptor = new DefaultFieldInterceptor(null, null, null, "MyClass", typeof(MyClass)); fieldInterceptionProxy.Should().Be.BinarySerializable(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-21 14:11:28
|
Revision: 5494 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5494&view=rev Author: fabiomaulo Date: 2011-03-21 14:11:22 +0000 (Mon, 21 Mar 2011) Log Message: ----------- Fix NH-2584 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs 2011-03-21 07:31:00 UTC (rev 5493) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs 2011-03-21 14:11:22 UTC (rev 5494) @@ -124,6 +124,10 @@ @event.Entity = entity; EntityState entityState = EntityState.Undefined; + if (ReferenceEquals(null, @event.EntityName)) + { + @event.EntityName = source.BestGuessEntityName(entity); + } // Check the persistence context for an entry relating to this // entity to be merged... Modified: trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2011-03-21 07:31:00 UTC (rev 5493) +++ trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2011-03-21 14:11:22 UTC (rev 5494) @@ -116,5 +116,19 @@ } } + [Test] + public void CanLoadAndSaveObjectInDifferentSessions() + { + Book book; + using (ISession s = OpenSession()) + { + book = s.Get<Book>(1); + } + + using (ISession s = OpenSession()) + { + s.Merge(book); + } + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-21 15:06:37
|
Revision: 5495 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5495&view=rev Author: fabiomaulo Date: 2011-03-21 15:06:30 +0000 (Mon, 21 Mar 2011) Log Message: ----------- Fix NH-2530 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Id/TableGenerator.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Id/TableGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Id/TableGenerator.cs 2011-03-21 14:11:22 UTC (rev 5494) +++ trunk/nhibernate/src/NHibernate/Id/TableGenerator.cs 2011-03-21 15:06:30 UTC (rev 5495) @@ -231,7 +231,15 @@ rs = qps.ExecuteReader(); if (!rs.Read()) { - string err = "could not read a hi value - you need to populate the table: " + tableName; + string err; + if (string.IsNullOrEmpty(whereClause)) + { + err = "could not read a hi value - you need to populate the table: " + tableName; + } + else + { + err = string.Format("could not read a hi value from table '{0}' using the where clause ({1})- you need to populate the table.", tableName, whereClause); + } log.Error(err); throw new IdentifierGenerationException(err); } Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Domain.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Domain.cs 2011-03-21 15:06:30 UTC (rev 5495) @@ -0,0 +1,14 @@ +namespace NHibernate.Test.NHSpecificTest.NH2530 +{ + public abstract class Product + { + public virtual int Id { get; set; } + public virtual string Title { get; set; } + } + + public class Customer + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Fixture.cs 2011-03-21 15:06:30 UTC (rev 5495) @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Text; +using Iesi.Collections.Generic; +using NHibernate.Dialect; +using NHibernate.Mapping; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2530 +{ + public class Fixture: BugTestCase + { + protected override void Configure(Cfg.Configuration configuration) + { + configuration.AddAuxiliaryDatabaseObject(CreateHighLowScript(new[] { typeof(Product) })); + } + + private IAuxiliaryDatabaseObject CreateHighLowScript(IEnumerable<System.Type> entities) + { + var script = new StringBuilder(1024); + script.AppendLine("DELETE FROM NextHighVaues;"); + script.AppendLine("ALTER TABLE NextHighVaues ADD Entity VARCHAR(128) NOT NULL;"); + script.AppendLine("CREATE NONCLUSTERED INDEX IdxNextHighVauesEntity ON NextHighVaues (Entity ASC);"); + script.AppendLine("GO"); + foreach (var entity in entities) + { + script.AppendLine(string.Format("INSERT INTO [NextHighVaues] (Entity, NextHigh) VALUES ('{0}',1);", entity.Name)); + } + return new SimpleAuxiliaryDatabaseObject(script.ToString(), null, new HashedSet<string> { typeof(MsSql2000Dialect).FullName, typeof(MsSql2005Dialect).FullName, typeof(MsSql2008Dialect).FullName }); + } + + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return (dialect is Dialect.MsSql2000Dialect); + } + + [Test] + public void WhenTryToGetHighThenExceptionShouldContainWhereClause() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var customer = new Customer { Name = "Mengano" }; + session.Executing(s => s.Persist(customer)).Throws().And.ValueOf.Message.Should().Contain("Entity = 'Customer'"); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2530/Mappings.hbm.xml 2011-03-21 15:06:30 UTC (rev 5495) @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Mapping extracted from ConfORM usage example (ConfOrm.UsageExamples.HighLowPerEntity) --> +<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + namespace="NHibernate.Test.NHSpecificTest.NH2530" + assembly="NHibernate.Test" xmlns="urn:nhibernate-mapping-2.2"> + <class name="Product" abstract="true"> + <id name="Id" type="Int32"> + <generator class="hilo"> + <param name="table">NextHighVaues</param> + <param name="column">NextHigh</param> + <param name="max_lo">100</param> + <param name="where">Entity = 'Product'</param> + </generator> + </id> + <discriminator /> + <property name="Title" /> + </class> + <class name="Customer"> + <id name="Id" type="Int32"> + <generator class="hilo"> + <param name="table">NextHighVaues</param> + <param name="column">NextHigh</param> + <param name="max_lo">100</param> + <param name="where">Entity = 'Customer'</param> + </generator> + </id> + <property name="Name" /> + </class> +</hibernate-mapping> \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-21 14:11:22 UTC (rev 5494) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-21 15:06:30 UTC (rev 5495) @@ -646,6 +646,8 @@ <Compile Include="NHSpecificTest\NH2484\Model.cs" /> <Compile Include="NHSpecificTest\NH2507\Animal.cs" /> <Compile Include="NHSpecificTest\NH2507\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2530\Domain.cs" /> + <Compile Include="NHSpecificTest\NH2530\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2565\Domain.cs" /> <Compile Include="NHSpecificTest\NH2565\Fixture.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> @@ -2470,6 +2472,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2530\Mappings.hbm.xml" /> <EmbeddedResource Include="DynamicProxyTests\InterfaceProxySerializationTests\ProxyImpl.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2565\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\AccessAndCorrectPropertyName\DogMapping.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-21 20:09:24
|
Revision: 5497 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5497&view=rev Author: fabiomaulo Date: 2011-03-21 20:09:18 +0000 (Mon, 21 Mar 2011) Log Message: ----------- Fix NH-2498 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs 2011-03-21 18:08:32 UTC (rev 5496) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassBinder.cs 2011-03-21 20:09:18 UTC (rev 5497) @@ -439,8 +439,9 @@ // Note : fetch="join" overrides default laziness bool isLazyTrue = !laziness.HasValue ? defaultLazy && fetchable.IsLazy - : laziness == HbmLaziness.Proxy; + : (laziness == HbmLaziness.Proxy || laziness == HbmLaziness.NoProxy); fetchable.IsLazy = isLazyTrue; + fetchable.UnwrapProxy = laziness == HbmLaziness.NoProxy; } protected void InitOuterJoinFetchSetting(HbmManyToMany manyToMany, IFetchable model) Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2011-03-21 18:08:32 UTC (rev 5496) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2011-03-21 20:09:18 UTC (rev 5497) @@ -26,7 +26,7 @@ { this.session = session; this.uninitializedFields = uninitializedFields; - this.unwrapProxyFieldNames = unwrapProxyFieldNames; + this.unwrapProxyFieldNames = unwrapProxyFieldNames ?? new HashedSet<string>(); this.entityName = entityName; this.mappedClass = mappedClass; } @@ -50,11 +50,7 @@ public bool IsInitializedField(string field) { - if (unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(field)) - { - return loadedUnwrapProxyFieldNames.Contains(field); - } - return uninitializedFields == null || !uninitializedFields.Contains(field); + return !IsUninitializedProperty(field) && !IsUninitializedAssociation(field); } public void MarkDirty() @@ -89,14 +85,16 @@ get { return initializing; } } - // NH Specific: Hibernate only deals with lazy properties here, we deal with - // both lazy properties and with no-proxy. public object Intercept(object target, string fieldName, object value) { + // NH Specific: Hibernate only deals with lazy properties here, we deal with + // both lazy properties and with no-proxy. if (initializing) + { return InvokeImplementation; + } - if (!IsUninitializedProperty(fieldName)) + if (IsInitializedField(fieldName)) { return value; } @@ -114,16 +112,20 @@ { return InitializeField(fieldName, target); } - - if (value.IsProxy() && unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(fieldName)) + + if (value.IsProxy() && IsUninitializedAssociation(fieldName)) { - var nhproxy = value as INHibernateProxy; - - return InitializeOrGetAssociation(nhproxy, fieldName); + var nhproxy = value as INHibernateProxy; + return InitializeOrGetAssociation(nhproxy, fieldName); } return InvokeImplementation; } + private bool IsUninitializedAssociation(string fieldName) + { + return unwrapProxyFieldNames.Contains(fieldName) && !loadedUnwrapProxyFieldNames.Contains(fieldName); + } + private bool IsUninitializedProperty(string fieldName) { return uninitializedFields != null && uninitializedFields.Contains(fieldName); Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2011-03-21 18:08:32 UTC (rev 5496) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2011-03-21 20:09:18 UTC (rev 5497) @@ -1,6 +1,8 @@ using System.Collections; +using NHibernate.Cfg.Loquacious; using NHibernate.Tuple.Entity; using NUnit.Framework; +using SharpTestsEx; namespace NHibernate.Test.GhostProperty { @@ -19,6 +21,11 @@ get { return new[] { "GhostProperty.Mappings.hbm.xml" }; } } + protected override void Configure(Cfg.Configuration configuration) + { + configuration.DataBaseIntegration(x=> x.LogFormatedSql = false); + } + protected override void OnSetUp() { using (var s = OpenSession()) @@ -109,6 +116,51 @@ } } + [Test] + public void WillLoadGhostAssociationOnAccess() + { + // NH-2498 + using (ISession s = OpenSession()) + { + Order order; + using (var ls = new SqlLogSpy()) + { + order = s.Get<Order>(1); + var logMessage = ls.GetWholeLog(); + logMessage.Should().Not.Contain("FROM Payment"); + } + order.Satisfy(o => !NHibernateUtil.IsPropertyInitialized(o, "Payment")); + // trigger on-access lazy load + var x = order.Payment; + order.Satisfy(o => NHibernateUtil.IsPropertyInitialized(o, "Payment")); + } + } + + [Test] + public void WhenGetThenLoadOnlyNoLazyPlainProperties() + { + using (ISession s = OpenSession()) + { + Order order; + using (var ls = new SqlLogSpy()) + { + order = s.Get<Order>(1); + var logMessage = ls.GetWholeLog(); + logMessage.Should().Not.Contain("ALazyProperty"); + logMessage.Should().Contain("NoLazyProperty"); + } + order.Satisfy(o => NHibernateUtil.IsPropertyInitialized(o, "NoLazyProperty")); + order.Satisfy(o => !NHibernateUtil.IsPropertyInitialized(o, "ALazyProperty")); + + using (var ls = new SqlLogSpy()) + { + var x = order.ALazyProperty; + var logMessage = ls.GetWholeLog(); + logMessage.Should().Contain("ALazyProperty"); + } + order.Satisfy(o => NHibernateUtil.IsPropertyInitialized(o, "ALazyProperty")); + } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml 2011-03-21 18:08:32 UTC (rev 5496) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml 2011-03-21 20:09:18 UTC (rev 5497) @@ -8,9 +8,12 @@ <generator class="assigned" /> </id> <many-to-one name="Payment" lazy="no-proxy"/> - </class> + <property name="ALazyProperty" lazy="true"/> + <property name="NoLazyProperty"/> + </class> + <class name="Payment" abstract="true"> <id name="Id"> <generator class="assigned" /> Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs 2011-03-21 18:08:32 UTC (rev 5496) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs 2011-03-21 20:09:18 UTC (rev 5497) @@ -10,6 +10,9 @@ get { return payment; } set { payment = value; } } + + public virtual string ALazyProperty { get; set; } + public virtual string NoLazyProperty { get; set; } } public abstract class Payment This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-03-22 17:01:20
|
Revision: 5500 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5500&view=rev Author: fabiomaulo Date: 2011-03-22 17:01:13 +0000 (Tue, 22 Mar 2011) Log Message: ----------- Fix NH-2591 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs trunk/nhibernate/src/NHibernate/Cfg/Environment.cs trunk/nhibernate/src/NHibernate/Cfg/Loquacious/DbIntegrationConfiguration.cs trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IBatcherConfiguration.cs trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IDbIntegrationConfiguration.cs trunk/nhibernate/src/NHibernate/Cfg/SettingsFactory.cs trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Insertordering/ trunk/nhibernate/src/NHibernate.Test/Insertordering/Group.cs trunk/nhibernate/src/NHibernate.Test/Insertordering/InsertOrderingFixture.cs trunk/nhibernate/src/NHibernate.Test/Insertordering/Mapping.hbm.xml trunk/nhibernate/src/NHibernate.Test/Insertordering/Membership.cs trunk/nhibernate/src/NHibernate.Test/Insertordering/User.cs Modified: trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -122,7 +122,7 @@ } } - public IDbCommand PrepareBatchCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) + public virtual IDbCommand PrepareBatchCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) { /* NH: * The code inside this block was added for a strange behaviour Modified: trunk/nhibernate/src/NHibernate/Cfg/Environment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -162,6 +162,9 @@ public const string LinqToHqlGeneratorsRegistry = "linqtohql.generatorsregistry"; + /// <summary> Enable ordering of insert statements for the purpose of more effecient batching.</summary> + public const string OrderInserts = "order_inserts"; + private static readonly Dictionary<string, string> GlobalProperties; private static IBytecodeProvider BytecodeProviderInstance; Modified: trunk/nhibernate/src/NHibernate/Cfg/Loquacious/DbIntegrationConfiguration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Loquacious/DbIntegrationConfiguration.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/Cfg/Loquacious/DbIntegrationConfiguration.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -207,6 +207,18 @@ return dbc; } + public IBatcherConfiguration OrderingInserts() + { + dbc.Configuration.SetProperty(Environment.OrderInserts, true.ToString().ToLowerInvariant()); + return this; + } + + public IBatcherConfiguration DisablingInsertsOrdering() + { + dbc.Configuration.SetProperty(Environment.OrderInserts, false.ToString().ToLowerInvariant()); + return this; + } + #endregion } @@ -337,6 +349,11 @@ set { configuration.SetProperty(Environment.BatchSize, value.ToString()); } } + public bool OrderInserts + { + set { configuration.SetProperty(Environment.OrderInserts, value.ToString().ToLowerInvariant()); } + } + public void TransactionFactory<TFactory>() where TFactory : ITransactionFactory { configuration.SetProperty(Environment.TransactionStrategy, typeof(TFactory).AssemblyQualifiedName); Modified: trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IBatcherConfiguration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IBatcherConfiguration.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IBatcherConfiguration.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -5,5 +5,7 @@ { IBatcherConfiguration Through<TBatcher>() where TBatcher : IBatcherFactory; IDbIntegrationConfiguration Each(short batchSize); + IBatcherConfiguration OrderingInserts(); + IBatcherConfiguration DisablingInsertsOrdering(); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IDbIntegrationConfiguration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IDbIntegrationConfiguration.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/Cfg/Loquacious/IDbIntegrationConfiguration.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -47,6 +47,7 @@ void Batcher<TBatcher>() where TBatcher : IBatcherFactory; short BatchSize { set; } + bool OrderInserts { set; } void TransactionFactory<TFactory>() where TFactory : ITransactionFactory; Modified: trunk/nhibernate/src/NHibernate/Cfg/SettingsFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/SettingsFactory.cs 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/Cfg/SettingsFactory.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -229,6 +229,10 @@ // TODO: Environment.BatchVersionedData settings.AdoBatchSize = PropertiesHelper.GetInt32(Environment.BatchSize, properties, 0); + bool orderInserts = PropertiesHelper.GetBoolean(Environment.OrderInserts, properties, (settings.AdoBatchSize > 0)); + log.Info("Order SQL inserts for batching: " + EnabledDisabled(orderInserts)); + settings.IsOrderInsertsEnabled = orderInserts; + bool wrapResultSets = PropertiesHelper.GetBoolean(Environment.WrapResultSets, properties, false); log.Debug("Wrap result sets: " + EnabledDisabled(wrapResultSets)); settings.IsWrapResultSetsEnabled = wrapResultSets; Modified: trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2011-03-22 17:01:13 UTC (rev 5500) @@ -114,7 +114,8 @@ <xs:enumeration value="use_sql_comments" /> <xs:enumeration value="format_sql" /> <xs:enumeration value="collectiontype.factory_class" /> - </xs:restriction> + <xs:enumeration value="order_inserts" /> + </xs:restriction> </xs:simpleType> </xs:attribute> </xs:extension> Added: trunk/nhibernate/src/NHibernate.Test/Insertordering/Group.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Insertordering/Group.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Insertordering/Group.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -0,0 +1,8 @@ +namespace NHibernate.Test.Insertordering +{ + public class Group + { + public virtual int Id { get; protected set; } + public virtual string Name { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/Insertordering/InsertOrderingFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Insertordering/InsertOrderingFixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Insertordering/InsertOrderingFixture.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -0,0 +1,146 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using NHibernate.AdoNet; +using NHibernate.Cfg; +using NHibernate.Cfg.Loquacious; +using NHibernate.Engine; +using NHibernate.SqlCommand; +using NHibernate.SqlTypes; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.Insertordering +{ + public class InsertOrderingFixture : TestCase + { + const int batchSize = 10; + const int instancesPerEach = 12; + const int typesOfEntities = 3; + protected override IList Mappings + { + get { return new[] {"Insertordering.Mapping.hbm.xml"}; } + } + + protected override string MappingsAssembly + { + get { return "NHibernate.Test"; } + } + + protected override void Configure(Configuration configuration) + { + configuration.DataBaseIntegration(x => + { + x.BatchSize = batchSize; + x.OrderInserts = true; + x.Batcher<StatsBatcherFactory>(); + }); + } + + [Test] + public void BatchOrdering() + { + using (ISession s = OpenSession()) + using (s.BeginTransaction()) + { + for (int i = 0; i < instancesPerEach; i++) + { + var user = new User {UserName = "user-" + i}; + var group = new Group {Name = "group-" + i}; + s.Save(user); + s.Save(group); + user.AddMembership(group); + } + StatsBatcher.Reset(); + s.Transaction.Commit(); + } + + int expectedBatchesPerEntity = (instancesPerEach / batchSize) + ((instancesPerEach % batchSize) == 0 ? 0 : 1); + StatsBatcher.BatchSizes.Count.Should().Be(expectedBatchesPerEntity * typesOfEntities); + + using (ISession s = OpenSession()) + { + s.BeginTransaction(); + IList users = s.CreateQuery("from User u left join fetch u.Memberships m left join fetch m.Group").List(); + foreach (object user in users) + { + s.Delete(user); + } + s.Transaction.Commit(); + } + } + + #region Nested type: StatsBatcher + + public class StatsBatcher : SqlClientBatchingBatcher + { + private static string batchSQL; + private static IList<int> batchSizes = new List<int>(); + private static int currentBatch = -1; + + public StatsBatcher(ConnectionManager connectionManager, IInterceptor interceptor) + : base(connectionManager, interceptor) {} + + public static IList<int> BatchSizes + { + get { return batchSizes; } + } + + public static void Reset() + { + batchSizes = new List<int>(); + currentBatch = -1; + batchSQL = null; + } + + public override IDbCommand PrepareBatchCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) + { + IDbCommand result = base.PrepareBatchCommand(type, sql, parameterTypes); + string sqlstring = sql.ToString(); + if (batchSQL == null || !sqlstring.Equals(batchSQL)) + { + currentBatch++; + batchSQL = sqlstring; + batchSizes.Insert(currentBatch, 0); + Console.WriteLine("--------------------------------------------------------"); + Console.WriteLine("Preparing statement [" + batchSQL + "]"); + } + return result; + } + + public override void AddToBatch(IExpectation expectation) + { + batchSizes[currentBatch]++; + Console.WriteLine("Adding to batch [" + batchSQL + "]"); + base.AddToBatch(expectation); + } + + protected override void DoExecuteBatch(IDbCommand ps) + { + Console.WriteLine("executing batch [" + batchSQL + "]"); + Console.WriteLine("--------------------------------------------------------"); + batchSQL = null; + base.DoExecuteBatch(ps); + } + } + + #endregion + + #region Nested type: StatsBatcherFactory + + public class StatsBatcherFactory : IBatcherFactory + { + #region IBatcherFactory Members + + public IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor) + { + return new StatsBatcher(connectionManager, interceptor); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/Insertordering/Mapping.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Insertordering/Mapping.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Insertordering/Mapping.hbm.xml 2011-03-22 17:01:13 UTC (rev 5500) @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping + xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.Insertordering" + assembly="NHibernate.Test"> + + <class name="User" table="INS_ORD_USR"> + <id name="Id"> + <generator class="increment"/> + </id> + <property name="UserName" column="USR_NM" /> + <set name="Memberships" inverse="true" cascade="all" access="field.camelcase"> + <key column="USR_ID"/> + <one-to-many class="Membership"/> + </set> + </class> + + <class name="Group" table="INS_ORD_GRP"> + <id name="Id"> + <generator class="increment"/> + </id> + <property name="Name"/> + </class> + + <class name="Membership" table="INS_ORD_MEM"> + <id name="Id"> + <generator class="increment" /> + </id> + <many-to-one name="User" class="User" column="USR_ID" cascade="all"/> + <many-to-one name="Group" class="Group" column="GRP_ID" cascade="all"/> + <property name="ActivationDate" type="timestamp" column="JN_DT"/> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/Insertordering/Membership.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Insertordering/Membership.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Insertordering/Membership.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -0,0 +1,23 @@ +using System; + +namespace NHibernate.Test.Insertordering +{ + public class Membership + { + protected Membership() {} + + public Membership(User user, Group @group) : this(user, group, DateTime.Now) {} + + public Membership(User user, Group @group, DateTime activationDate) + { + User = user; + Group = group; + ActivationDate = activationDate; + } + + public virtual int Id { get; protected set; } + public virtual User User { get; private set; } + public virtual Group Group { get; private set; } + public virtual DateTime ActivationDate { get; private set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/Insertordering/User.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Insertordering/User.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Insertordering/User.cs 2011-03-22 17:01:13 UTC (rev 5500) @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Iesi.Collections.Generic; + +namespace NHibernate.Test.Insertordering +{ + public class User + { + private ISet<Membership> memberships; + public User() + { + memberships = new HashedSet<Membership>(); + } + public virtual int Id { get; protected set; } + public virtual string UserName { get; set; } + public virtual IEnumerable<Membership> Memberships + { + get { return memberships; } + } + + public virtual Membership AddMembership(Group group) + { + var membership = new Membership(this, group); + memberships.Add(membership); + return membership; + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-22 05:14:35 UTC (rev 5499) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-22 17:01:13 UTC (rev 5500) @@ -459,6 +459,10 @@ <Compile Include="Immutable\Info.cs" /> <Compile Include="Immutable\Party.cs" /> <Compile Include="Immutable\Plan.cs" /> + <Compile Include="Insertordering\Group.cs" /> + <Compile Include="Insertordering\InsertOrderingFixture.cs" /> + <Compile Include="Insertordering\Membership.cs" /> + <Compile Include="Insertordering\User.cs" /> <Compile Include="LazyOneToOne\Employee.cs" /> <Compile Include="LazyOneToOne\Employment.cs" /> <Compile Include="LazyOneToOne\LazyOneToOneTest.cs" /> @@ -2472,6 +2476,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="Insertordering\Mapping.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2530\Mappings.hbm.xml" /> <EmbeddedResource Include="DynamicProxyTests\InterfaceProxySerializationTests\ProxyImpl.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2565\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |