You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(248) |
May
(82) |
Jun
(90) |
Jul
(177) |
Aug
(253) |
Sep
(157) |
Oct
(151) |
Nov
(143) |
Dec
(278) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(152) |
Feb
(107) |
Mar
(177) |
Apr
(133) |
May
(259) |
Jun
(81) |
Jul
(119) |
Aug
(306) |
Sep
(416) |
Oct
(240) |
Nov
(329) |
Dec
(206) |
2006 |
Jan
(466) |
Feb
(382) |
Mar
(153) |
Apr
(162) |
May
(133) |
Jun
(21) |
Jul
(18) |
Aug
(37) |
Sep
(97) |
Oct
(114) |
Nov
(110) |
Dec
(28) |
2007 |
Jan
(74) |
Feb
(65) |
Mar
(49) |
Apr
(76) |
May
(43) |
Jun
(15) |
Jul
(68) |
Aug
(55) |
Sep
(63) |
Oct
(59) |
Nov
(70) |
Dec
(66) |
2008 |
Jan
(71) |
Feb
(60) |
Mar
(120) |
Apr
(31) |
May
(48) |
Jun
(81) |
Jul
(107) |
Aug
(51) |
Sep
(80) |
Oct
(83) |
Nov
(83) |
Dec
(79) |
2009 |
Jan
(83) |
Feb
(110) |
Mar
(97) |
Apr
(91) |
May
(291) |
Jun
(250) |
Jul
(197) |
Aug
(58) |
Sep
(54) |
Oct
(122) |
Nov
(68) |
Dec
(34) |
2010 |
Jan
(50) |
Feb
(17) |
Mar
(63) |
Apr
(61) |
May
(84) |
Jun
(81) |
Jul
(138) |
Aug
(144) |
Sep
(78) |
Oct
(26) |
Nov
(30) |
Dec
(61) |
2011 |
Jan
(33) |
Feb
(35) |
Mar
(166) |
Apr
(221) |
May
(109) |
Jun
(76) |
Jul
(27) |
Aug
(37) |
Sep
(1) |
Oct
(4) |
Nov
(2) |
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2013 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(1) |
2014 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <aye...@us...> - 2010-01-27 15:08:35
|
Revision: 4937 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4937&view=rev Author: ayenderahien Date: 2010-01-27 15:07:21 +0000 (Wed, 27 Jan 2010) Log Message: ----------- Fixing NH-2077 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Classic/ParserHelper.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Model.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/ParserHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Classic/ParserHelper.cs 2010-01-27 14:40:36 UTC (rev 4936) +++ trunk/nhibernate/src/NHibernate/Hql/Classic/ParserHelper.cs 2010-01-27 15:07:21 UTC (rev 4937) @@ -7,7 +7,7 @@ { public const string HqlVariablePrefix = ":"; - public const string HqlSeparators = " \n\r\f\t,()=<>&|+-=/*'^![]#~\\"; + public const string HqlSeparators = " \n\r\f\t,()=<>&|+-=/*'^![]#~\\;"; //NOTICE: no " or . since they are part of (compound) identifiers public const string PathSeparators = "."; Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Fixture.cs 2010-01-27 15:07:21 UTC (rev 4937) @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Transactions; +using NHibernate.Dialect; +using NHibernate.Impl; +using NUnit.Framework; +using NHibernate.Criterion; + +namespace NHibernate.Test.NHSpecificTest.NH2077 +{ + [TestFixture] + public class Fixture : BugTestCase + { + + protected override bool AppliesTo(NHibernate.Dialect.Dialect dialect) + { + return dialect is MsSql2000Dialect; + } + + [Test] + public void CanExecuteMultipleQueriesUsingNativeSQL() + { + using (var s = OpenSession()) + { + s.CreateSQLQuery( + @" +DELETE FROM Person WHERE Id = :userId; +UPDATE Person SET Id = :deletedUserId WHERE Id = :userId; +DELETE FROM Person WHERE Id = :userId; +") + .SetParameter("userId",1) + .SetParameter("deletedUserId", 1) + .ExecuteUpdate(); + } + } + + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Mappings.hbm.xml 2010-01-27 15:07:21 UTC (rev 4937) @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2077"> + + <class name="Person"> + <id name="Id"> + <generator class="increment" /> + </id> + <property name="Name"/> + + <set name="Children"> + <key column="ParentId"/> + <one-to-many class="Person"/> + </set> + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2077/Model.cs 2010-01-27 15:07:21 UTC (rev 4937) @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2077 +{ + public class Person + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual ICollection<Person> Children { get; set; } + } + +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-27 14:40:36 UTC (rev 4936) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-27 15:07:21 UTC (rev 4937) @@ -700,6 +700,8 @@ <Compile Include="NHSpecificTest\NH2030\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2065\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2065\Model.cs" /> + <Compile Include="NHSpecificTest\NH2077\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2077\Model.cs" /> <Compile Include="NHSpecificTest\NH473\Child.cs" /> <Compile Include="NHSpecificTest\NH473\Fixture.cs" /> <Compile Include="NHSpecificTest\NH473\Parent.cs" /> @@ -2117,6 +2119,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2077\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2020\Mappings.hbm.xml" /> <EmbeddedResource Include="GhostProperty\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2065\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-27 14:40:51
|
Revision: 4936 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4936&view=rev Author: ayenderahien Date: 2010-01-27 14:40:36 +0000 (Wed, 27 Jan 2010) Log Message: ----------- Fixing NH-2082 applied patch from Bartosz Pierzchlewicz Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Transaction/AdoTransaction.cs Modified: trunk/nhibernate/src/NHibernate/Transaction/AdoTransaction.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Transaction/AdoTransaction.cs 2010-01-27 14:38:34 UTC (rev 4935) +++ trunk/nhibernate/src/NHibernate/Transaction/AdoTransaction.cs 2010-01-27 14:40:36 UTC (rev 4936) @@ -115,6 +115,11 @@ { throw new TransactionException("Cannot restart transaction after failed commit"); } + + if (isolationLevel == IsolationLevel.Unspecified) + { + isolationLevel = session.Factory.Settings.IsolationLevel; + } log.Debug(string.Format("Begin ({0})", isolationLevel)); @@ -122,11 +127,6 @@ { if (isolationLevel == IsolationLevel.Unspecified) { - isolationLevel = session.Factory.Settings.IsolationLevel; - } - - if (isolationLevel == IsolationLevel.Unspecified) - { trans = session.Connection.BeginTransaction(); } else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-27 14:38:49
|
Revision: 4935 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4935&view=rev Author: ayenderahien Date: 2010-01-27 14:38:34 +0000 (Wed, 27 Jan 2010) Log Message: ----------- Fixing NH-2084 - multiple future queries using same parameter name. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2010-01-27 14:00:14 UTC (rev 4934) +++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2010-01-27 14:38:34 UTC (rev 4935) @@ -38,10 +38,8 @@ private readonly Dialect.Dialect dialect; private bool forceCacheRefresh; private QueryParameters combinedParameters; - private readonly List<string> namedParametersThatAreSafeToDuplicate = new List<string>(); private FlushMode flushMode = FlushMode.Unspecified; private FlushMode sessionFlushMode = FlushMode.Unspecified; - private static readonly Regex parseParameterListOrignialName = new Regex(@"(?<orgname>.*?)_\d+_", RegexOptions.Compiled); public MultiQueryImpl(ISessionImplementor session) { @@ -75,7 +73,6 @@ public IMultiQuery SetParameter(string name, object val, IType type) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetParameter(name, val, type); @@ -85,7 +82,6 @@ public IMultiQuery SetParameter(string name, object val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetParameter(name, val); @@ -95,7 +91,6 @@ public IMultiQuery SetParameterList(string name, ICollection vals, IType type) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetParameterList(name, vals, type); @@ -105,7 +100,6 @@ public IMultiQuery SetParameterList(string name, ICollection vals) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetParameterList(name, vals); @@ -115,7 +109,6 @@ public IMultiQuery SetAnsiString(string name, string val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetAnsiString(name, val); @@ -125,7 +118,6 @@ public IMultiQuery SetBinary(string name, byte[] val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetBinary(name, val); @@ -135,7 +127,6 @@ public IMultiQuery SetBoolean(string name, bool val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetBoolean(name, val); @@ -145,7 +136,6 @@ public IMultiQuery SetByte(string name, byte val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetByte(name, val); @@ -155,7 +145,6 @@ public IMultiQuery SetCharacter(string name, char val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetCharacter(name, val); @@ -165,7 +154,6 @@ public IMultiQuery SetDateTime(string name, DateTime val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetDateTime(name, val); @@ -175,7 +163,6 @@ public IMultiQuery SetDecimal(string name, decimal val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetDecimal(name, val); @@ -185,7 +172,6 @@ public IMultiQuery SetDouble(string name, double val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetDouble(name, val); @@ -195,7 +181,6 @@ public IMultiQuery SetEntity(string name, object val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetEntity(name, val); @@ -205,7 +190,6 @@ public IMultiQuery SetEnum(string name, Enum val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetEnum(name, val); @@ -215,7 +199,6 @@ public IMultiQuery SetInt16(string name, short val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetInt16(name, val); @@ -225,7 +208,6 @@ public IMultiQuery SetInt32(string name, int val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetInt32(name, val); @@ -235,7 +217,6 @@ public IMultiQuery SetInt64(string name, long val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetInt64(name, val); @@ -245,7 +226,6 @@ public IMultiQuery SetSingle(string name, float val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetSingle(name, val); @@ -255,7 +235,6 @@ public IMultiQuery SetString(string name, string val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetString(name, val); @@ -265,7 +244,6 @@ public IMultiQuery SetGuid(string name, Guid val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetGuid(name, val); @@ -275,7 +253,6 @@ public IMultiQuery SetTime(string name, DateTime val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetTime(name, val); @@ -285,7 +262,6 @@ public IMultiQuery SetTimestamp(string name, DateTime val) { - namedParametersThatAreSafeToDuplicate.Add(name); foreach (IQuery query in queries) { query.SetTimestamp(name, val); @@ -797,9 +773,14 @@ combinedQueryParameters.NamedParameters = new Dictionary<string, TypedValue>(); ArrayList positionalParameterTypes = new ArrayList(); ArrayList positionalParameterValues = new ArrayList(); + int index = 0; foreach (QueryParameters queryParameters in Parameters) { - CopyNamedParametersDictionary(combinedQueryParameters.NamedParameters, queryParameters.NamedParameters); + foreach (KeyValuePair<string, TypedValue> dictionaryEntry in queryParameters.NamedParameters) + { + combinedQueryParameters.NamedParameters.Add(dictionaryEntry.Key + index, dictionaryEntry.Value); + } + index += 1; positionalParameterTypes.AddRange(queryParameters.PositionalParameterTypes); positionalParameterValues.AddRange(queryParameters.PositionalParameterValues); } @@ -818,37 +799,6 @@ } } - private void CopyNamedParametersDictionary(IDictionary<string, TypedValue> dest, IDictionary<string, TypedValue> src) - { - foreach (KeyValuePair<string, TypedValue> dictionaryEntry in src) - { - if (dest.ContainsKey(dictionaryEntry.Key)) - { - if (IsParameterSafeToDuplicate(dictionaryEntry.Key)) - continue; //we specify it for all the queries, so it is okay. - - throw new QueryException( - string.Format( - "The named parameter {0} was used in more than one query. Either give unique names to your parameters, or use the multi query SetParameter() methods to set the named parameter", - dictionaryEntry.Key)); - } - dest.Add(dictionaryEntry.Key, dictionaryEntry.Value); - } - } - - private bool IsParameterSafeToDuplicate(string name) - { - if (namedParametersThatAreSafeToDuplicate.Contains(name)) - return true; - Match match = parseParameterListOrignialName.Match(name); - if (match != null) - { - string originalName = match.Groups["orgname"].Value; - return namedParametersThatAreSafeToDuplicate.Contains(originalName); - } - return false; - } - private void ThrowIfKeyAlreadyExists(string key) { if (criteriaResultPositions.ContainsKey(key)) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs 2010-01-27 14:00:14 UTC (rev 4934) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs 2010-01-27 14:38:34 UTC (rev 4935) @@ -94,5 +94,37 @@ } } } + + [Test] + public void CanExecuteMultipleQueryWithSameParameterName() + { + using (var s = sessions.OpenSession()) + { + IgnoreThisTestIfMultipleQueriesArentSupportedByDriver(); + + var meContainer = s.CreateQuery("from Person p where p.Id = :personId") + .SetParameter("personId", 1) + .FutureValue<Person>(); + + var possiblefriends = s.CreateQuery("from Person p where p.Id != :personId") + .SetParameter("personId", 2) + .Future<Person>(); + + using (var logSpy = new SqlLogSpy()) + { + var me = meContainer.Value; + + foreach (var person in possiblefriends) + { + } + + var events = logSpy.Appender.GetEvents(); + Assert.AreEqual(1, events.Length); + var wholeLog = logSpy.GetWholeLog(); + Assert.True(wholeLog.Contains("@p0 = 1 [Type: Int32 (0)], @p1 = 2 [Type: Int32 (0)]")); + } + } + + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-27 14:00:21
|
Revision: 4934 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4934&view=rev Author: ayenderahien Date: 2010-01-27 14:00:14 +0000 (Wed, 27 Jan 2010) Log Message: ----------- Applying patch from Richard Birkb, fixing NH-2086 Fixing schema issue with SQL CE Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/MsSqlCeDialect.cs trunk/nhibernate/src/NHibernate.Test/DialectTest/SqlCEDialectFixture.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSqlCeDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MsSqlCeDialect.cs 2010-01-27 13:53:45 UTC (rev 4933) +++ trunk/nhibernate/src/NHibernate/Dialect/MsSqlCeDialect.cs 2010-01-27 14:00:14 UTC (rev 4934) @@ -1,7 +1,9 @@ using System.Data; using System.Data.Common; +using System.Text; using NHibernate.Dialect.Schema; -using Environment=NHibernate.Cfg.Environment; +using NHibernate.Util; +using Environment = NHibernate.Cfg.Environment; namespace NHibernate.Dialect { @@ -97,5 +99,51 @@ { return new MsSqlCeDataBaseSchema(connection); } - } + + public override string Qualify(string catalog, string schema, string table) + { + // SQL Server Compact doesn't support Schemas. So join schema name and table name with underscores + // similar to the SQLLite dialect. + + var qualifiedName = new StringBuilder(); + bool quoted = false; + + if (!string.IsNullOrEmpty(catalog)) + { + qualifiedName.Append(catalog).Append(StringHelper.Dot); + } + + var tableName = new StringBuilder(); + if (!string.IsNullOrEmpty(schema)) + { + if (schema.StartsWith(OpenQuote.ToString())) + { + schema = schema.Substring(1, schema.Length - 1); + quoted = true; + } + if (schema.EndsWith(CloseQuote.ToString())) + { + schema = schema.Substring(0, schema.Length - 1); + quoted = true; + } + tableName.Append(schema).Append(StringHelper.Underscore); + } + + if (table.StartsWith(OpenQuote.ToString())) + { + table = table.Substring(1, table.Length - 1); + quoted = true; + } + if (table.EndsWith(CloseQuote.ToString())) + { + table = table.Substring(0, table.Length - 1); + quoted = true; + } + + string name = tableName.Append(table).ToString(); + if (quoted) + name = OpenQuote + name + CloseQuote; + return qualifiedName.Append(name).ToString(); + } + } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/DialectTest/SqlCEDialectFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/DialectTest/SqlCEDialectFixture.cs 2010-01-27 13:53:45 UTC (rev 4933) +++ trunk/nhibernate/src/NHibernate.Test/DialectTest/SqlCEDialectFixture.cs 2010-01-27 14:00:14 UTC (rev 4934) @@ -7,10 +7,17 @@ [TestFixture] public class SqlCEDialectFixture { - [Test] + private MsSqlCeDialect dialect; + + [SetUp] + public void SetUp() + { + dialect = new MsSqlCeDialect(); + } + + [Test] public void BinaryBlob_mapping_to_SqlCe_types() { - Dialect dialect = new MsSqlCeDialect(); SimpleValue sv = new SimpleValue(); sv.TypeName = NHibernateUtil.BinaryBlob.Name; Column column = new Column(); @@ -26,5 +33,68 @@ column.Length = 8001; Assert.AreEqual("IMAGE", column.GetSqlType(dialect, null)); } - } + + [Test] + public void QuotedSchemaNameWithSqlCE() + { + Table tbl = new Table(); + tbl.Schema = "`schema`"; + tbl.Name = "`name`"; + + Assert.AreEqual("\"schema_name\"", tbl.GetQualifiedName(dialect)); + Assert.AreEqual("\"schema_table\"", dialect.Qualify("", "\"schema\"", "\"table\"")); + } + + [Test] + public void QuotedTableNameWithoutSchemaWithSqlCE() + { + Table tbl = new Table(); + tbl.Name = "`name`"; + + Assert.AreEqual("\"name\"", tbl.GetQualifiedName(dialect)); + } + + [Test] + public void QuotedSchemaNameWithUnqoutedTableInSqlCE() + { + Table tbl = new Table(); + tbl.Schema = "`schema`"; + tbl.Name = "name"; + + Assert.AreEqual("\"schema_name\"", tbl.GetQualifiedName(dialect)); + Assert.AreEqual("\"schema_table\"", dialect.Qualify("", "\"schema\"", "table")); + } + + [Test] + public void QuotedCatalogSchemaNameWithSqlCE() + { + Table tbl = new Table(); + tbl.Catalog = "dbo"; + tbl.Schema = "`schema`"; + tbl.Name = "`name`"; + + Assert.AreEqual("dbo.\"schema_name\"", tbl.GetQualifiedName(dialect)); + Assert.AreEqual("dbo.\"schema_table\"", dialect.Qualify("dbo", "\"schema\"", "\"table\"")); + } + + [Test] + public void QuotedTableNameWithSqlCE() + { + Table tbl = new Table(); + tbl.Name = "`Group`"; + + Assert.AreEqual("\"Group\"", tbl.GetQualifiedName(dialect)); + } + + [Test] + public void SchemaNameWithSqlCE() + { + Table tbl = new Table(); + tbl.Schema = "schema"; + tbl.Name = "name"; + + Assert.AreEqual("schema_name", tbl.GetQualifiedName(dialect)); + Assert.AreEqual("schema_table", dialect.Qualify("", "schema", "table")); + } + } } \ 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: <aye...@us...> - 2010-01-27 13:53:51
|
Revision: 4933 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4933&view=rev Author: ayenderahien Date: 2010-01-27 13:53:45 +0000 (Wed, 27 Jan 2010) Log Message: ----------- Adding appropriate alert for non auto prop ghost property Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-26 23:28:18 UTC (rev 4932) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-27 13:53:45 UTC (rev 4933) @@ -303,7 +303,8 @@ { foreach (var prop in persistentClass.PropertyClosureIterator) { - if (prop.IsLazy == false && prop.UnwrapProxy) + if (prop.IsLazy == false && + prop.UnwrapProxy == false) continue; var getter = prop.GetGetter(persistentClass.MappedClass); Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-26 23:28:18 UTC (rev 4932) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-27 13:53:45 UTC (rev 4933) @@ -1,6 +1,7 @@ using System.Collections; using NHibernate.ByteCode.Castle; using NHibernate.Cfg; +using NHibernate.Tuple.Entity; using NUnit.Framework; namespace NHibernate.Test.GhostProperty @@ -8,6 +9,8 @@ [TestFixture] public class GhostPropertyFixture : TestCase { + private string log; + protected override string MappingsAssembly { get { return "NHibernate.Test"; } @@ -55,7 +58,22 @@ } } + protected override void BuildSessionFactory() + { + using (var logSpy = new LogSpy(typeof(EntityMetamodel))) + { + base.BuildSessionFactory(); + log = logSpy.GetWholeLog(); + } + } + [Test] + public void ShouldGenerateErrorForNonAutoPropGhostProp() + { + Assert.IsTrue(log.Contains("Lazy or ghost property NHibernate.Test.GhostProperty.Order.Payment is not an auto property, which may result in uninitialized property access")); + } + + [Test] public void CanGetActualValueFromLazyManyToOne() { using (ISession s = OpenSession()) Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs 2010-01-26 23:28:18 UTC (rev 4932) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs 2010-01-27 13:53:45 UTC (rev 4933) @@ -3,7 +3,13 @@ public class Order { public virtual int Id { get; set; } - public virtual Payment Payment { get; set; } + private Payment payment; + + public virtual Payment Payment + { + get { return payment; } + set { payment = value; } + } } public abstract class Payment This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-01-26 23:28:26
|
Revision: 4932 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4932&view=rev Author: ricbrown Date: 2010-01-26 23:28:18 +0000 (Tue, 26 Jan 2010) Log Message: ----------- Fix NH-2020 (ISQLExceptionConverter does not get called if batch size enabled) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/AdoNet/SqlClientSqlCommandSet.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Model.cs Modified: trunk/nhibernate/src/NHibernate/AdoNet/SqlClientSqlCommandSet.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/SqlClientSqlCommandSet.cs 2010-01-26 09:25:25 UTC (rev 4931) +++ trunk/nhibernate/src/NHibernate/AdoNet/SqlClientSqlCommandSet.cs 2010-01-26 23:28:18 UTC (rev 4932) @@ -111,16 +111,10 @@ if (Connection == null) throw new ArgumentNullException( "Connection was not set! You must set the connection property before calling ExecuteNonQuery()"); - try - { - if (CountOfCommands == 0) - return 0; - return doExecuteNonQuery(); - } - catch (Exception e) - { - throw new HibernateException("An exception occurred when executing batch queries", e); - } + + if (CountOfCommands == 0) + return 0; + return doExecuteNonQuery(); } public SqlConnection Connection Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Fixture.cs 2010-01-26 23:28:18 UTC (rev 4932) @@ -0,0 +1,75 @@ +using System; + +using NUnit.Framework; + +using NHibernate.Dialect; +using NHibernate.Exceptions; +using NHibernate.Test.ExceptionsTest; + +namespace NHibernate.Test.NHSpecificTest.NH2020 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void Configure(Cfg.Configuration configuration) + { + configuration.SetProperty(Cfg.Environment.BatchSize, "1"); + + configuration.SetProperty( Cfg.Environment.SqlExceptionConverter, + typeof (MSSQLExceptionConverterExample).AssemblyQualifiedName); + } + + protected override bool AppliesTo(NHibernate.Dialect.Dialect dialect) + { + return dialect is MsSql2000Dialect; + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete("from One"); + s.Delete("from Many"); + tx.Commit(); + } + } + + [Test] + public void ISQLExceptionConverter_gets_called_if_batch_size_enabled() + { + long oneId; + + using(var s = OpenSession()) + using(var tx = s.BeginTransaction()) + { + var one = new One(); + s.Save(one); + + var many = new Many { One = one }; + s.Save(many); + + tx.Commit(); + + oneId = one.Id; + } + + using(ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + var one = s.Load<One>(oneId); + + try + { + s.Delete(one); + tx.Commit(); + Assert.Fail("DELETE should have failed"); + } + catch (Exception ex) + { + Assert.IsInstanceOf<ConstraintViolationException>(ex); + } + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Mappings.hbm.xml 2010-01-26 23:28:18 UTC (rev 4932) @@ -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.NH2020"> + + <class name="One"> + <id name="Id"> + <generator class="native"/> + </id> + </class> + + <class name="Many"> + <id name="Id"> + <generator class="native"/> + </id> + <many-to-one name="One" /> + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2020/Model.cs 2010-01-26 23:28:18 UTC (rev 4932) @@ -0,0 +1,13 @@ +namespace NHibernate.Test.NHSpecificTest.NH2020 +{ + public class One + { + public virtual long Id { get; set; } + } + + public class Many + { + public virtual long Id { get; set; } + public virtual One One { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-26 09:25:25 UTC (rev 4931) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-26 23:28:18 UTC (rev 4932) @@ -667,6 +667,8 @@ <Compile Include="NHSpecificTest\NH1989\Model.cs" /> <Compile Include="NHSpecificTest\NH2009\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2009\Model.cs" /> + <Compile Include="NHSpecificTest\NH2020\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2020\Model.cs" /> <Compile Include="NHSpecificTest\NH2044\DomainClass.cs" /> <Compile Include="NHSpecificTest\NH2044\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH2055\AuxType.cs" /> @@ -2115,6 +2117,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2020\Mappings.hbm.xml" /> <EmbeddedResource Include="GhostProperty\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2065\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2009\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-26 09:25:33
|
Revision: 4931 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4931&view=rev Author: ayenderahien Date: 2010-01-26 09:25:25 +0000 (Tue, 26 Jan 2010) Log Message: ----------- Simplifying no-proxy implementation, adding comments to point out differences from hibernate Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Mapping/Property.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-25 21:57:55 UTC (rev 4930) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-26 09:25:25 UTC (rev 4931) @@ -13,7 +13,8 @@ [NonSerialized] private ISessionImplementor session; private ISet<string> uninitializedFields; - private ISet<string> unwrapProxyFieldNames; + private readonly ISet<string> unwrapProxyFieldNames; + private readonly ISet<string> loadedUnwrapProxyFieldNames = new HashedSet<string>(); private readonly string entityName; [NonSerialized] @@ -47,6 +48,10 @@ public bool IsInitializedField(string field) { + if (unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(field)) + { + return loadedUnwrapProxyFieldNames.Contains(field); + } return uninitializedFields == null || !uninitializedFields.Contains(field); } @@ -77,6 +82,8 @@ 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) { if (initializing) @@ -97,25 +104,18 @@ } if (value is INHibernateProxy && unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(fieldName)) { - return InitializeOrGetAssociation((INHibernateProxy)value); + return InitializeOrGetAssociation((INHibernateProxy)value, fieldName); } return InvokeImplementation; } - private object InitializeOrGetAssociation(INHibernateProxy value) + private object InitializeOrGetAssociation(INHibernateProxy value, string fieldName) { if(value.HibernateLazyInitializer.IsUninitialized) { value.HibernateLazyInitializer.Initialize(); - var association = value.HibernateLazyInitializer.GetImplementation(session); - //var narrowedProxy = session.PersistenceContext.ProxyFor(association); - // we set the narrowed impl here to be able to get it back in the future - value.HibernateLazyInitializer.SetImplementation(association); - var entityPersister = session.GetEntityPersister(value.HibernateLazyInitializer.EntityName, value); - var key = new EntityKey(value.HibernateLazyInitializer.Identifier, - entityPersister, - session.EntityMode); - session.PersistenceContext.RemoveProxy(key); + value.HibernateLazyInitializer.Unwrap = true; // means that future Load/Get from the session will get the implementation + loadedUnwrapProxyFieldNames.Add(fieldName); } return value.HibernateLazyInitializer.GetImplementation(session); } Modified: trunk/nhibernate/src/NHibernate/Mapping/Property.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-25 21:57:55 UTC (rev 4930) +++ trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-26 09:25:25 UTC (rev 4931) @@ -261,28 +261,10 @@ { get { - if (propertyValue is ToOne) - { - // both many-to-one and one-to-one are represented as a - // Property. EntityPersister is relying on this value to - // determine "lazy fetch groups" in terms of field-level - // interception. So we need to make sure that we return - // true here for the case of many-to-one and one-to-one - // with lazy="no-proxy" - // - // * impl note - lazy="no-proxy" currently forces both - // lazy and unwrap to be set to true. The other case we - // are extremely interested in here is that of lazy="proxy" - // where lazy is set to true, but unwrap is set to false. - // thus we use both here under the assumption that this - // return is really only ever used during persister - // construction to determine the lazy property/field fetch - // groupings. If that assertion changes then this check - // needs to change as well. Partially, this is an issue with - // the overloading of the term "lazy" here... - ToOne toOneValue = (ToOne)propertyValue; - return toOneValue.IsLazy && toOneValue.UnwrapProxy; - } + // NH Specific: Hibernate doesn't make a distinction between + // lazy and no-proxy, but NHibernate does. While Hibernate tracks + // just whatever a property is lazy, we need to track lazy/no-proxy seperatedly. + return isLazy; } set { isLazy = value; } @@ -305,6 +287,12 @@ set { nodeName = value; } } + // both many-to-one and one-to-one are represented as a + // Property. EntityPersister is relying on this value to + // determine "lazy fetch groups" in terms of field-level + // interception. So we need to make sure that we return + // true here for the case of many-to-one and one-to-one + // with lazy="no-proxy" public bool UnwrapProxy { get; set; } } } Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-25 21:57:55 UTC (rev 4930) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-26 09:25:25 UTC (rev 4931) @@ -67,6 +67,16 @@ } [Test] + public void WillNotLoadGhostPropertyByDefault() + { + using (ISession s = OpenSession()) + { + var order = s.Get<Order>(1); + Assert.IsFalse(NHibernateUtil.IsPropertyInitialized(order, "Payment")); + } + } + + [Test] public void GhostPropertyMaintainIdentityMap() { using (ISession s = OpenSession()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-25 21:58:02
|
Revision: 4930 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4930&view=rev Author: ayenderahien Date: 2010-01-25 21:57:55 +0000 (Mon, 25 Jan 2010) Log Message: ----------- Removing unused code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2010-01-25 10:27:03 UTC (rev 4929) +++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2010-01-25 21:57:55 UTC (rev 4930) @@ -720,14 +720,6 @@ } } - public void ClearProxyFor(IEntityPersister persister, EntityKey key) - { - if (!persister.HasProxy || key == null) - return; - - proxiesByKey.Remove(key); - } - /// <summary> /// Return the existing proxy associated with the given <tt>EntityKey</tt>, or the /// third argument (the entity associated with the key) if no proxy exists. Init This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-25 10:27:10
|
Revision: 4929 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4929&view=rev Author: ayenderahien Date: 2010-01-25 10:27:03 +0000 (Mon, 25 Jan 2010) Log Message: ----------- Removing test that shows how a feature does NOT work Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-25 07:44:42 UTC (rev 4928) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-25 10:27:03 UTC (rev 4929) @@ -77,7 +77,7 @@ } } - [Test] + [Test, Ignore("This shows an expected edge case")] public void GhostPropertyMaintainIdentityMapUsingGet() { using (ISession s = OpenSession()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-25 07:44:56
|
Revision: 4928 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4928&view=rev Author: ayenderahien Date: 2010-01-25 07:44:42 +0000 (Mon, 25 Jan 2010) Log Message: ----------- Fixing ayende-being-stupid error Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-25 07:33:00 UTC (rev 4927) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-25 07:44:42 UTC (rev 4928) @@ -708,7 +708,7 @@ public bool HasUnwrapProxyForProperties { - get { return hasUnwrapProxyForProperties;c } + get { return hasUnwrapProxyForProperties; } } public bool HasNonIdentifierPropertyNamedId This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-25 07:33:07
|
Revision: 4927 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4927&view=rev Author: ayenderahien Date: 2010-01-25 07:33:00 +0000 (Mon, 25 Jan 2010) Log Message: ----------- Changing ghost property terminology from ghost to unwrap proxy (more accurate) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs trunk/nhibernate/src/NHibernate/Mapping/Property.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -107,7 +107,7 @@ var value = new ManyToOne(table); BindManyToOne(manyToOneMapping, value, propertyName, true); property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas); - property.IsGhostProperty = manyToOneMapping.Lazy == HbmLaziness.NoProxy; + property.UnwrapProxy = manyToOneMapping.Lazy == HbmLaziness.NoProxy; BindManyToOneProperty(manyToOneMapping, property); } else if ((componentMapping = entityPropertyMapping as HbmComponent) != null) Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -13,18 +13,18 @@ [NonSerialized] private ISessionImplementor session; private ISet<string> uninitializedFields; - private ISet<string> uninitializedGhostFieldNames; + private ISet<string> unwrapProxyFieldNames; private readonly string entityName; [NonSerialized] private bool initializing; private bool isDirty; - protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> uninitializedGhostFieldNames, string entityName) + protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> unwrapProxyFieldNames, string entityName) { this.session = session; this.uninitializedFields = uninitializedFields; - this.uninitializedGhostFieldNames = uninitializedGhostFieldNames; + this.unwrapProxyFieldNames = unwrapProxyFieldNames; this.entityName = entityName; } @@ -95,7 +95,7 @@ { return InitializeField(fieldName, target); } - if (value is INHibernateProxy && uninitializedGhostFieldNames != null && uninitializedGhostFieldNames.Contains(fieldName)) + if (value is INHibernateProxy && unwrapProxyFieldNames != null && unwrapProxyFieldNames.Contains(fieldName)) { return InitializeOrGetAssociation((INHibernateProxy)value); } Modified: trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -5,8 +5,8 @@ { public class DefaultFieldInterceptor : AbstractFieldInterceptor { - public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> uninitializedGhostFieldNames, string entityName) - : base(session, uninitializedFields, uninitializedGhostFieldNames, entityName) + public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> unwrapProxyFieldNames, string entityName) + : base(session, uninitializedFields, unwrapProxyFieldNames, entityName) { } } Modified: trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -34,13 +34,13 @@ public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName, ISet<string> uninitializedFieldNames, - ISet<string> uninitializedGhostFieldNames, + ISet<string> unwrapProxyFieldNames, ISessionImplementor session) { var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; if (fieldInterceptorAccessor != null) { - var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, uninitializedGhostFieldNames, entityName); + var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, unwrapProxyFieldNames, entityName); fieldInterceptorAccessor.FieldInterceptor = fieldInterceptorImpl; return fieldInterceptorImpl; } Modified: trunk/nhibernate/src/NHibernate/Mapping/Property.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -305,6 +305,6 @@ set { nodeName = value; } } - public bool IsGhostProperty { get; set; } + public bool UnwrapProxy { get; set; } } } Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -153,9 +153,9 @@ { hasLazy = true; } - if (prop.IsGhostProperty) + if (prop.UnwrapProxy) { - hasGhostProperties = true; + hasUnwrapProxyForProperties = true; } propertyLaziness[i] = lazyProperty; @@ -238,12 +238,12 @@ VerifyCanInterceptPropertiesForLazyOrGhostProperties(persistentClass); } } - if(hasGhostProperties) + if(hasUnwrapProxyForProperties) { if (lazy == false) { log.WarnFormat("Disabled ghost properies fetching for {0} beacuse it does not support lazy at the entity level", name); - hasGhostProperties = false; + hasUnwrapProxyForProperties = false; } else { @@ -303,7 +303,7 @@ { foreach (var prop in persistentClass.PropertyClosureIterator) { - if (prop.IsLazy == false && prop.IsGhostProperty) + if (prop.IsLazy == false && prop.UnwrapProxy) continue; var getter = prop.GetGetter(persistentClass.MappedClass); @@ -683,7 +683,7 @@ #region Tuplizer private readonly EntityEntityModeToTuplizerMapping tuplizerMapping; - private bool hasGhostProperties; + private bool hasUnwrapProxyForProperties; public IEntityTuplizer GetTuplizer(EntityMode entityMode) { @@ -706,9 +706,9 @@ get { return naturalIdPropertyNumbers != null; } } - public bool HasGhostProperties + public bool HasUnwrapProxyForProperties { - get { return hasGhostProperties; } + get { return hasUnwrapProxyForProperties;c } } public bool HasNonIdentifierPropertyNamedId Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -25,7 +25,7 @@ private readonly bool islifecycleImplementor; private readonly bool isValidatableImplementor; private readonly HashedSet<string> lazyPropertyNames = new HashedSet<string>(); - private readonly HashedSet<string> ghostPropertyNames = new HashedSet<string>(); + private readonly HashedSet<string> unwrapProxyPropertyNames = new HashedSet<string>(); [NonSerialized] private IReflectionOptimizer optimizer; private readonly IProxyValidator proxyValidator; @@ -55,8 +55,8 @@ { if (property.IsLazy) lazyPropertyNames.Add(property.Name); - if (property.IsGhostProperty) - ghostPropertyNames.Add(property.Name); + if (property.UnwrapProxy) + unwrapProxyPropertyNames.Add(property.Name); } SetReflectionOptimizer(); @@ -79,7 +79,7 @@ { get { - return (EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties) + return (EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties) && FieldInterceptionHelper.IsInstrumented(MappedClass); } } @@ -104,12 +104,12 @@ if (optimizer == null) { log.Debug("Create Instantiator without optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties); + return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties); } else { log.Debug("Create Instantiator using optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties); + return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties); } } @@ -229,7 +229,7 @@ HashedSet<string> lazyProps = lazyPropertiesAreUnfetched && EntityMetamodel.HasLazyProperties ? lazyPropertyNames : null; //TODO: if we support multiple fetch groups, we would need // to clone the set of lazy properties! - FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, lazyProps, ghostPropertyNames, session); + FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, lazyProps, unwrapProxyPropertyNames, session); } } Modified: trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -22,7 +22,7 @@ private readonly IProxyFactory proxyFactory; - private readonly bool hasLazyProperties; + private readonly bool generateFieldInterceptionProxy; private readonly bool embeddedIdentifier; @@ -54,14 +54,14 @@ } } - public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer, IProxyFactory proxyFactory, bool hasLazyProperties) + public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer, IProxyFactory proxyFactory, bool generateFieldInterceptionProxy) { mappedClass = persistentClass.MappedClass; proxyInterface = persistentClass.ProxyInterface; embeddedIdentifier = persistentClass.HasEmbeddedIdentifier; this.optimizer = optimizer; this.proxyFactory = proxyFactory; - this.hasLazyProperties = hasLazyProperties; + this.generateFieldInterceptionProxy = generateFieldInterceptionProxy; try { @@ -88,7 +88,7 @@ { throw new InstantiationException("Cannot instantiate abstract class or interface: ", mappedClass); } - if (hasLazyProperties) + if (generateFieldInterceptionProxy) { return proxyFactory.GetFieldInterceptionProxy(); } Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-24 22:44:45 UTC (rev 4926) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-25 07:33:00 UTC (rev 4927) @@ -77,5 +77,18 @@ } } + [Test] + public void GhostPropertyMaintainIdentityMapUsingGet() + { + using (ISession s = OpenSession()) + { + var payment = s.Load<Payment>(1); + var order = s.Get<Order>(1); + + Assert.AreSame(order.Payment, payment); + } + } + + } } \ 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: <aye...@us...> - 2010-01-24 22:44:52
|
Revision: 4926 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4926&view=rev Author: ayenderahien Date: 2010-01-24 22:44:45 +0000 (Sun, 24 Jan 2010) Log Message: ----------- modify ghost property functionality to use lazy='no-proxy' Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2010-01-24 22:44:45 UTC (rev 4926) @@ -678,14 +678,6 @@ public bool notnullSpecified; /// <remarks/> - [System.Xml.Serialization.XmlAttributeAttribute("force-load-on-property-access")] - public bool forceloadonpropertyaccess; - - /// <remarks/> - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool forceloadonpropertyaccessSpecified; - - /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(false)] public bool unique; Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 22:44:45 UTC (rev 4926) @@ -28,11 +28,6 @@ get { return optimisticlock; } } - public bool ForceLoadOnPropertyAccess - { - get { return forceloadonpropertyaccess; } - } - #endregion #region Overrides of AbstractDecoratable Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 22:44:45 UTC (rev 4926) @@ -107,7 +107,7 @@ var value = new ManyToOne(table); BindManyToOne(manyToOneMapping, value, propertyName, true); property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas); - property.IsGhostProperty = manyToOneMapping.ForceLoadOnPropertyAccess; + property.IsGhostProperty = manyToOneMapping.Lazy == HbmLaziness.NoProxy; BindManyToOneProperty(manyToOneMapping, property); } else if ((componentMapping = entityPropertyMapping as HbmComponent) != null) Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2010-01-24 22:44:45 UTC (rev 4926) @@ -720,6 +720,14 @@ } } + public void ClearProxyFor(IEntityPersister persister, EntityKey key) + { + if (!persister.HasProxy || key == null) + return; + + proxiesByKey.Remove(key); + } + /// <summary> /// Return the existing proxy associated with the given <tt>EntityKey</tt>, or the /// third argument (the entity associated with the key) if no proxy exists. Init Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 22:44:45 UTC (rev 4926) @@ -108,9 +108,14 @@ { value.HibernateLazyInitializer.Initialize(); var association = value.HibernateLazyInitializer.GetImplementation(session); - var narrowedProxy = session.PersistenceContext.ProxyFor(association); + //var narrowedProxy = session.PersistenceContext.ProxyFor(association); // we set the narrowed impl here to be able to get it back in the future - value.HibernateLazyInitializer.SetImplementation(narrowedProxy); + value.HibernateLazyInitializer.SetImplementation(association); + var entityPersister = session.GetEntityPersister(value.HibernateLazyInitializer.EntityName, value); + var key = new EntityKey(value.HibernateLazyInitializer.Identifier, + entityPersister, + session.EntityMode); + session.PersistenceContext.RemoveProxy(key); } return value.HibernateLazyInitializer.GetImplementation(session); } Modified: trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2010-01-24 22:44:45 UTC (rev 4926) @@ -879,8 +879,6 @@ </xs:attribute> <xs:attribute name="unique" default="false" type="xs:boolean"> </xs:attribute> - <xs:attribute name="force-load-on-property-access" default="false" type="xs:boolean"> - </xs:attribute> <xs:attribute name="unique-key" type="xs:string" /> <xs:attribute name="index" type="xs:string" /> <xs:attribute name="cascade" type="xs:string" /> Modified: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml 2010-01-24 21:46:35 UTC (rev 4925) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml 2010-01-24 22:44:45 UTC (rev 4926) @@ -7,7 +7,7 @@ <id name="Id"> <generator class="assigned" /> </id> - <many-to-one name="Payment" force-load-on-property-access="true"/> + <many-to-one name="Payment" lazy="no-proxy"/> </class> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-24 21:46:57
|
Revision: 4925 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4925&view=rev Author: ayenderahien Date: 2010-01-24 21:46:35 +0000 (Sun, 24 Jan 2010) Log Message: ----------- adding support for ghost properties Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs trunk/nhibernate/src/NHibernate/Event/Default/AbstractSaveEventListener.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Mapping/Property.cs trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/GhostProperty/ 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/MappingSchema/Hbm.generated.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -672,11 +672,19 @@ /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute("not-null")] public bool notnull; - + /// <remarks/> [System.Xml.Serialization.XmlIgnoreAttribute()] public bool notnullSpecified; - + + /// <remarks/> + [System.Xml.Serialization.XmlAttributeAttribute("force-load-on-property-access")] + public bool forceloadonpropertyaccess; + + /// <remarks/> + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool forceloadonpropertyaccessSpecified; + /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(false)] Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -28,6 +28,11 @@ get { return optimisticlock; } } + public bool ForceLoadOnPropertyAccess + { + get { return forceloadonpropertyaccess; } + } + #endregion #region Overrides of AbstractDecoratable Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -107,6 +107,7 @@ var value = new ManyToOne(table); BindManyToOne(manyToOneMapping, value, propertyName, true); property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas); + property.IsGhostProperty = manyToOneMapping.ForceLoadOnPropertyAccess; BindManyToOneProperty(manyToOneMapping, property); } else if ((componentMapping = entityPropertyMapping as HbmComponent) != null) Modified: trunk/nhibernate/src/NHibernate/Event/Default/AbstractSaveEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/AbstractSaveEventListener.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Event/Default/AbstractSaveEventListener.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -292,7 +292,7 @@ { if (FieldInterceptionHelper.IsInstrumented(entity)) { - IFieldInterceptor interceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, persister.EntityName, null, source); + IFieldInterceptor interceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, persister.EntityName, null, null, source); interceptor.MarkDirty(); } } Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -1,6 +1,7 @@ using System; using Iesi.Collections.Generic; using NHibernate.Engine; +using NHibernate.Proxy; namespace NHibernate.Intercept { @@ -12,16 +13,18 @@ [NonSerialized] private ISessionImplementor session; private ISet<string> uninitializedFields; + private ISet<string> uninitializedGhostFieldNames; private readonly string entityName; [NonSerialized] private bool initializing; private bool isDirty; - protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, string entityName) + protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> uninitializedGhostFieldNames, string entityName) { this.session = session; this.uninitializedFields = uninitializedFields; + this.uninitializedGhostFieldNames = uninitializedGhostFieldNames; this.entityName = entityName; } @@ -74,11 +77,9 @@ get { return initializing; } } - public object Intercept(object target, string fieldName) + public object Intercept(object target, string fieldName, object value) { - if (initializing || - uninitializedFields == null || - !uninitializedFields.Contains(fieldName)) + if (initializing) return InvokeImplementation; if (session == null) @@ -90,11 +91,38 @@ throw new LazyInitializationException("session is not connected"); } + if (uninitializedFields != null && uninitializedFields.Contains(fieldName)) + { + return InitializeField(fieldName, target); + } + if (value is INHibernateProxy && uninitializedGhostFieldNames != null && uninitializedGhostFieldNames.Contains(fieldName)) + { + return InitializeOrGetAssociation((INHibernateProxy)value); + } + return InvokeImplementation; + } + + private object InitializeOrGetAssociation(INHibernateProxy value) + { + if(value.HibernateLazyInitializer.IsUninitialized) + { + value.HibernateLazyInitializer.Initialize(); + var association = value.HibernateLazyInitializer.GetImplementation(session); + var narrowedProxy = session.PersistenceContext.ProxyFor(association); + // we set the narrowed impl here to be able to get it back in the future + value.HibernateLazyInitializer.SetImplementation(narrowedProxy); + } + return value.HibernateLazyInitializer.GetImplementation(session); + } + + private object InitializeField(string fieldName, object target) + { object result; initializing = true; try { - result = ((ILazyPropertyInitializer)session.Factory.GetEntityPersister(entityName)).InitializeLazyProperty(fieldName, target, session); + var lazyPropertyInitializer = ((ILazyPropertyInitializer) session.Factory.GetEntityPersister(entityName)); + result = lazyPropertyInitializer.InitializeLazyProperty(fieldName, target, session); } finally { Modified: trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -5,8 +5,8 @@ { public class DefaultFieldInterceptor : AbstractFieldInterceptor { - public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, string entityName) - : base(session, uninitializedFields, entityName) + public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, ISet<string> uninitializedGhostFieldNames, string entityName) + : base(session, uninitializedFields, uninitializedGhostFieldNames, entityName) { } } Modified: trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -32,12 +32,15 @@ return fieldInterceptorAccessor == null ? null : fieldInterceptorAccessor.FieldInterceptor; } - public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName, ISet<string> uninitializedFieldNames, ISessionImplementor session) + public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName, + ISet<string> uninitializedFieldNames, + ISet<string> uninitializedGhostFieldNames, + ISessionImplementor session) { var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; if (fieldInterceptorAccessor != null) { - var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, entityName); + var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, uninitializedGhostFieldNames, entityName); fieldInterceptorAccessor.FieldInterceptor = fieldInterceptorImpl; return fieldInterceptorImpl; } Modified: trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -28,6 +28,6 @@ void ClearDirty(); /// <summary> Intercept field set/get </summary> - object Intercept(object target, string fieldName); + object Intercept(object target, string fieldName, object value); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/Property.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Mapping/Property.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -132,10 +132,10 @@ { bool[] columnUpdateability = propertyValue.ColumnUpdateability; return updateable && - ( - // columnUpdateability.Length == 0 || - !ArrayHelper.IsAllFalse(columnUpdateability) - ); + ( + // columnUpdateability.Length == 0 || + !ArrayHelper.IsAllFalse(columnUpdateability) + ); } set { updateable = value; } } @@ -146,10 +146,10 @@ { bool[] columnInsertability = propertyValue.ColumnInsertability; return insertable && - ( - columnInsertability.Length == 0 || - !ArrayHelper.IsAllFalse(columnInsertability) - ); + ( + columnInsertability.Length == 0 || + !ArrayHelper.IsAllFalse(columnInsertability) + ); } set { insertable = value; } } @@ -206,7 +206,7 @@ public MetaAttribute GetMetaAttribute(string attributeName) { - if(metaAttributes == null) + if (metaAttributes == null) { return null; } @@ -226,7 +226,7 @@ { if (propertyValue is SimpleValue) { - return ((SimpleValue) propertyValue).NullValue; + return ((SimpleValue)propertyValue).NullValue; } else return null; @@ -304,5 +304,7 @@ get { return nodeName; } set { nodeName = value; } } + + public bool IsGhostProperty { get; set; } } } Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -3615,7 +3615,7 @@ } else { - IFieldInterceptor fieldInterceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, null, session); + IFieldInterceptor fieldInterceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, null, null, session); fieldInterceptor.MarkDirty(); } } Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -153,6 +153,11 @@ { hasLazy = true; } + if (prop.IsGhostProperty) + { + hasGhostProperties = true; + } + propertyLaziness[i] = lazyProperty; propertyNames[i] = properties[i].Name; @@ -230,20 +235,23 @@ else { log.Info("lazy property fetching available for: " + name); - foreach (var prop in persistentClass.PropertyClosureIterator) - { - if (prop.IsLazy == false) - continue; - - var getter = prop.GetGetter(persistentClass.MappedClass); - if(getter.Method == null || - getter.Method.IsDefined(typeof(CompilerGeneratedAttribute), false) == false) - { - log.ErrorFormat("Lazy property {0}.{1} is not an auto property, which may result in uninitialized property access", persistentClass.EntityName, prop.Name); - } - } + VerifyCanInterceptPropertiesForLazyOrGhostProperties(persistentClass); } } + if(hasGhostProperties) + { + if (lazy == false) + { + log.WarnFormat("Disabled ghost properies fetching for {0} beacuse it does not support lazy at the entity level", name); + hasGhostProperties = false; + } + else + { + log.Info("Ghost property fetching available for: " + name); + if (hasLazy == false) // avoid double checking + VerifyCanInterceptPropertiesForLazyOrGhostProperties(persistentClass); + } + } mutable = persistentClass.IsMutable; @@ -291,6 +299,22 @@ tuplizerMapping = new EntityEntityModeToTuplizerMapping(persistentClass, this); } + private static void VerifyCanInterceptPropertiesForLazyOrGhostProperties(PersistentClass persistentClass) + { + foreach (var prop in persistentClass.PropertyClosureIterator) + { + if (prop.IsLazy == false && prop.IsGhostProperty) + continue; + + var getter = prop.GetGetter(persistentClass.MappedClass); + if(getter.Method == null || + getter.Method.IsDefined(typeof(CompilerGeneratedAttribute), false) == false) + { + log.ErrorFormat("Lazy or ghost property {0}.{1} is not an auto property, which may result in uninitialized property access", persistentClass.EntityName, prop.Name); + } + } + } + private ValueInclusion DetermineInsertValueGenerationType(Mapping.Property mappingProperty, StandardProperty runtimeProperty) { if (runtimeProperty.IsInsertGenerated) @@ -659,6 +683,7 @@ #region Tuplizer private readonly EntityEntityModeToTuplizerMapping tuplizerMapping; + private bool hasGhostProperties; public IEntityTuplizer GetTuplizer(EntityMode entityMode) { @@ -681,6 +706,11 @@ get { return naturalIdPropertyNumbers != null; } } + public bool HasGhostProperties + { + get { return hasGhostProperties; } + } + public bool HasNonIdentifierPropertyNamedId { get { return hasNonIdentifierPropertyNamedId; } Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -25,6 +25,7 @@ private readonly bool islifecycleImplementor; private readonly bool isValidatableImplementor; private readonly HashedSet<string> lazyPropertyNames = new HashedSet<string>(); + private readonly HashedSet<string> ghostPropertyNames = new HashedSet<string>(); [NonSerialized] private IReflectionOptimizer optimizer; private readonly IProxyValidator proxyValidator; @@ -54,6 +55,8 @@ { if (property.IsLazy) lazyPropertyNames.Add(property.Name); + if (property.IsGhostProperty) + ghostPropertyNames.Add(property.Name); } SetReflectionOptimizer(); @@ -74,10 +77,10 @@ public override bool IsInstrumented { - get { - return - EntityMetamodel.HasLazyProperties && - FieldInterceptionHelper.IsInstrumented(MappedClass); + get + { + return (EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties) + && FieldInterceptionHelper.IsInstrumented(MappedClass); } } @@ -101,12 +104,12 @@ if (optimizer == null) { log.Debug("Create Instantiator without optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties); + return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties); } else { log.Debug("Create Instantiator using optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties); + return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasGhostProperties); } } @@ -226,7 +229,7 @@ HashedSet<string> lazyProps = lazyPropertiesAreUnfetched && EntityMetamodel.HasLazyProperties ? lazyPropertyNames : null; //TODO: if we support multiple fetch groups, we would need // to clone the set of lazy properties! - FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, lazyProps, session); + FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, lazyProps, ghostPropertyNames, session); } } Modified: trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2010-01-24 21:46:35 UTC (rev 4925) @@ -879,6 +879,8 @@ </xs:attribute> <xs:attribute name="unique" default="false" type="xs:boolean"> </xs:attribute> + <xs:attribute name="force-load-on-property-access" default="false" type="xs:boolean"> + </xs:attribute> <xs:attribute name="unique-key" type="xs:string" /> <xs:attribute name="index" type="xs:string" /> <xs:attribute name="cascade" type="xs:string" /> Modified: trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -18,20 +18,22 @@ { if (ReflectHelper.IsPropertyGet(invocation.Method)) { - var result = FieldInterceptor.Intercept(invocation.InvocationTarget, ReflectHelper.GetPropertyName(invocation.Method)); - if (result == AbstractFieldInterceptor.InvokeImplementation) + invocation.Proceed(); // get the existing value + + var result = FieldInterceptor.Intercept( + invocation.InvocationTarget, + ReflectHelper.GetPropertyName(invocation.Method), + invocation.ReturnValue); + + if (result != AbstractFieldInterceptor.InvokeImplementation) { - invocation.Proceed(); - } - else - { invocation.ReturnValue = result; } } else if (ReflectHelper.IsPropertySet(invocation.Method)) { FieldInterceptor.MarkDirty(); - FieldInterceptor.Intercept(invocation.InvocationTarget, ReflectHelper.GetPropertyName(invocation.Method)); + FieldInterceptor.Intercept(invocation.InvocationTarget, ReflectHelper.GetPropertyName(invocation.Method), null); invocation.Proceed(); } } Property changes on: trunk/nhibernate/src/NHibernate.Test/GhostProperty ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/GhostPropertyFixture.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -0,0 +1,81 @@ +using System.Collections; +using NHibernate.ByteCode.Castle; +using NHibernate.Cfg; +using NUnit.Framework; + +namespace NHibernate.Test.GhostProperty +{ + [TestFixture] + public class GhostPropertyFixture : TestCase + { + protected override string MappingsAssembly + { + get { return "NHibernate.Test"; } + } + + protected override IList Mappings + { + get { return new[] { "GhostProperty.Mappings.hbm.xml" }; } + } + + protected override void Configure(NHibernate.Cfg.Configuration configuration) + { + configuration.SetProperty(Environment.ProxyFactoryFactoryClass, + typeof(ProxyFactoryFactory).AssemblyQualifiedName); + } + + protected override void OnSetUp() + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + var wireTransfer = new WireTransfer + { + Id = 1 + }; + s.Persist(wireTransfer); + s.Persist(new Order + { + Id = 1, + Payment = wireTransfer + }); + tx.Commit(); + } + + } + + protected override void OnTearDown() + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.Delete("from Order"); + s.Delete("from Payment"); + tx.Commit(); + } + } + + [Test] + public void CanGetActualValueFromLazyManyToOne() + { + using (ISession s = OpenSession()) + { + var order = s.Get<Order>(1); + + Assert.IsTrue(order.Payment is WireTransfer); + } + } + + [Test] + public void GhostPropertyMaintainIdentityMap() + { + using (ISession s = OpenSession()) + { + var order = s.Get<Order>(1); + + Assert.AreSame(order.Payment, s.Load<Payment>(1)); + } + } + + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Mappings.hbm.xml 2010-01-24 21:46:35 UTC (rev 4925) @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.GhostProperty"> + + <class name="Order" table="Orders"> + <id name="Id"> + <generator class="assigned" /> + </id> + <many-to-one name="Payment" force-load-on-property-access="true"/> + </class> + + + <class name="Payment" abstract="true"> + <id name="Id"> + <generator class="assigned" /> + </id> + <discriminator column="Type" type="System.String"/> + <subclass name="WireTransfer" discriminator-value="WT"> + + </subclass> + <subclass name="CreditCard" discriminator-value="CC"> + + </subclass> + + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/GhostProperty/Order.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -0,0 +1,16 @@ +namespace NHibernate.Test.GhostProperty +{ + public class Order + { + public virtual int Id { get; set; } + public virtual Payment Payment { get; set; } + } + + public abstract class Payment + { + public virtual int Id { get; set; } + } + + public class WireTransfer : Payment{} + public class CreditCard : Payment { } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2010-01-24 21:46:35 UTC (rev 4925) @@ -85,7 +85,7 @@ [Test] public void ShouldGenerateErrorForNonAutoPropLazyProp() { - Assert.IsTrue(log.Contains("Lazy property NHibernate.Test.LazyProperty.Book.ALotOfText is not an auto property, which may result in uninitialized property access")); + Assert.IsTrue(log.Contains("Lazy or ghost property NHibernate.Test.LazyProperty.Book.ALotOfText is not an auto property, which may result in uninitialized property access")); } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-24 17:41:59 UTC (rev 4924) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-24 21:46:35 UTC (rev 4925) @@ -341,6 +341,8 @@ <Compile Include="GenericTest\SetGeneric\A.cs" /> <Compile Include="GenericTest\SetGeneric\B.cs" /> <Compile Include="GenericTest\SetGeneric\SetGenericFixture.cs" /> + <Compile Include="GhostProperty\Order.cs" /> + <Compile Include="GhostProperty\GhostPropertyFixture.cs" /> <Compile Include="HQL\Animal.cs" /> <Compile Include="HQL\Ast\Address.cs" /> <Compile Include="HQL\Ast\Animal.cs" /> @@ -2113,6 +2115,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="GhostProperty\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2065\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2009\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1989\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-24 17:42:07
|
Revision: 4924 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4924&view=rev Author: ayenderahien Date: 2010-01-24 17:41:59 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Adding error in the log about not using auto prop Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 16:46:51 UTC (rev 4923) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 17:41:59 UTC (rev 4924) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using Iesi.Collections.Generic; using log4net; using NHibernate.Engine; @@ -229,6 +230,18 @@ else { log.Info("lazy property fetching available for: " + name); + foreach (var prop in persistentClass.PropertyClosureIterator) + { + if (prop.IsLazy == false) + continue; + + var getter = prop.GetGetter(persistentClass.MappedClass); + if(getter.Method == null || + getter.Method.IsDefined(typeof(CompilerGeneratedAttribute), false) == false) + { + log.ErrorFormat("Lazy property {0}.{1} is not an auto property, which may result in uninitialized property access", persistentClass.EntityName, prop.Name); + } + } } } Modified: trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2010-01-24 16:46:51 UTC (rev 4923) +++ trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs 2010-01-24 17:41:59 UTC (rev 4924) @@ -1,6 +1,8 @@ using System.Collections; +using log4net.Core; using NHibernate.ByteCode.Castle; using NHibernate.Cfg; +using NHibernate.Tuple.Entity; using NUnit.Framework; namespace NHibernate.Test.LazyProperty @@ -8,6 +10,8 @@ [TestFixture] public class LazyPropertyFixture : TestCase { + private string log; + protected override string MappingsAssembly { get { return "NHibernate.Test"; } @@ -24,6 +28,15 @@ typeof(ProxyFactoryFactory).AssemblyQualifiedName); } + protected override void BuildSessionFactory() + { + using (var logSpy = new LogSpy(typeof(EntityMetamodel))) + { + base.BuildSessionFactory(); + log = logSpy.GetWholeLog(); + } + } + protected override void OnSetUp() { using (var s = OpenSession()) @@ -70,6 +83,12 @@ } [Test] + public void ShouldGenerateErrorForNonAutoPropLazyProp() + { + Assert.IsTrue(log.Contains("Lazy property NHibernate.Test.LazyProperty.Book.ALotOfText is not an auto property, which may result in uninitialized property access")); + } + + [Test] public void PropertyLoadedNotInitializedWhenUsingGet() { using (ISession s = OpenSession()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-24 16:47:04
|
Revision: 4923 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4923&view=rev Author: ayenderahien Date: 2010-01-24 16:46:51 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Implementing lazy properties * Removing ignore from the lazy property fixture * Adding LazyFieldInterceptor impl for Castle. Adding IFieldInterceptorAccessor to allow setting the field interceptor Adding convenience methods to detect property invocations * Adding DefaultFieldInterceptor - since we don't need one tied to the actual field interception impl * Removing temporary #region * Detecting usage of non collection lazy properties in entity meta model and considering this for instrumented fields * Implementing FieldInterceptionHelper Delegating responsibility for detecting interception to the proxy factory * Adding support for detecting lazy properties in the mapping * Simplifying code * Removed overly complex code * Binding properties laziness * Adding the ability to create field interception proxy to proxy factories. * Will create field interception proxy when needed LazyPropertyFixture basic test now works * Fixing off by one error * Adding more tests to verify lazy properties actually work * Implementing empty impl of the new field interception capabilities to other proxy factories impl * Updating loaded sln projects Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.ByteCode.Castle.csproj trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.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.ByteCode.Spring/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/SetFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.build trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj trunk/nhibernate/src/NHibernate.sln Added Paths: ----------- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs Modified: trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -36,5 +36,7 @@ */ IProxyValidator ProxyValidator { get; } + + bool IsInstrumented(System.Type entityClass); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -22,6 +22,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return lazy; } + } + #endregion #region Overrides of AbstractDecoratable Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -17,6 +17,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -23,6 +23,11 @@ get { return node; } } + public bool IsLazyProperty + { + get { return lazy; } + } + public string Name { get { return name; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -18,6 +18,11 @@ get { return null; } } + public bool IsLazyProperty + { + get { return false; } + } + public string EmbeddedNode { get { return node; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -70,6 +70,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return false; } + } + public string Access { get { return access; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -56,6 +56,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return false; } + } + public string Access { get { return access; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -21,6 +21,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -18,6 +18,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -56,5 +56,10 @@ } #endregion + + public bool IsLazyProperty + { + get { return false; } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -76,5 +76,10 @@ { get { return lazySpecified ? lazy : (HbmLaziness?)null; } } + + public bool IsLazyProperty + { + get { return Lazy == HbmLaziness.Proxy; } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -21,6 +21,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -13,6 +13,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return lazy; } + } + public string Access { get { return access; } @@ -62,7 +67,7 @@ unique = unique, uniqueSpecified = true, uniquekey = uniquekey, - index = index + index = index, }; } } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -22,6 +22,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -5,5 +5,6 @@ string Name { get; } string Access { get; } bool OptimisticLock { get; } + bool IsLazyProperty { get; } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -362,6 +362,7 @@ Name = propertyMapping.Name, PropertyAccessorName = propertyAccessorName, Value = value, + IsLazy = propertyMapping.IsLazyProperty, IsOptimisticLocked = propertyMapping.OptimisticLock, MetaAttributes = GetMetas(propertyMapping, inheritedMetas) }; Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -7,6 +7,8 @@ [Serializable] public abstract class AbstractFieldInterceptor : IFieldInterceptor { + public static readonly object InvokeImplementation = new object(); + [NonSerialized] private ISessionImplementor session; private ISet<string> uninitializedFields; @@ -72,41 +74,34 @@ get { return initializing; } } - protected internal object Intercept(object target, string fieldName, object value) + public object Intercept(object target, string fieldName) { - if (initializing) + if (initializing || + uninitializedFields == null || + !uninitializedFields.Contains(fieldName)) + return InvokeImplementation; + + if (session == null) { - return value; + throw new LazyInitializationException("entity with lazy properties is not associated with a session"); } - - if (uninitializedFields != null && uninitializedFields.Contains(fieldName)) + if (!session.IsOpen || !session.IsConnected) { - if (session == null) - { - throw new LazyInitializationException("entity with lazy properties is not associated with a session"); - } - else if (!session.IsOpen || !session.IsConnected) - { - throw new LazyInitializationException("session is not connected"); - } + throw new LazyInitializationException("session is not connected"); + } - object result; - initializing = true; - try - { - result = ((ILazyPropertyInitializer)session.Factory.GetEntityPersister(entityName)).InitializeLazyProperty(fieldName, target, session); - } - finally - { - initializing = false; - } - uninitializedFields = null; //let's assume that there is only one lazy fetch group, for now! - return result; + object result; + initializing = true; + try + { + result = ((ILazyPropertyInitializer)session.Factory.GetEntityPersister(entityName)).InitializeLazyProperty(fieldName, target, session); } - else + finally { - return value; + initializing = false; } + uninitializedFields = null; //let's assume that there is only one lazy fetch group, for now! + return result; } } } Added: trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -0,0 +1,13 @@ +using Iesi.Collections.Generic; +using NHibernate.Engine; + +namespace NHibernate.Intercept +{ + public class DefaultFieldInterceptor : AbstractFieldInterceptor + { + public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, string entityName) + : base(session, uninitializedFields, entityName) + { + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -7,44 +7,44 @@ public static class FieldInterceptionHelper { // VERY IMPORTANT!!!! - This class needs to be free of any static references - // to any Castle classes. Otherwise, users will always need both + // to any Castle/Spring/LinFu classes. Otherwise, users will always need both // on their classpaths no matter which (if either) they use. // // Another option here would be to remove the Hibernate.isPropertyInitialized() // method and have the users go through the SessionFactory to get this information. - - + public static bool IsInstrumented(System.Type entityClass) { - // TODO : Here code - return false; + // NH Specific: + // unlike Hibernate, NHibernate assumes that any class is valid for interception + // because we don't try to handle field interception + return Cfg.Environment.BytecodeProvider.ProxyFactoryFactory.IsInstrumented(entityClass); } - + public static bool IsInstrumented(object entity) { - return entity != null && IsInstrumented(entity.GetType()); + return entity is IFieldInterceptorAccessor; } - + public static IFieldInterceptor ExtractFieldInterceptor(object entity) { - if (entity == null) - { - return null; - } - // TODO : Here code to extract the Field Interceptor - return null; + var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; + return fieldInterceptorAccessor == null ? null : fieldInterceptorAccessor.FieldInterceptor; } - + public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName, ISet<string> uninitializedFieldNames, ISessionImplementor session) { - if (entity != null) + var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; + if (fieldInterceptorAccessor != null) { - // TODO : Here code to inject the Field Interceptor + var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, entityName); + fieldInterceptorAccessor.FieldInterceptor = fieldInterceptorImpl; + return fieldInterceptorImpl; } return null; } - - public static void ClearDirty(object entity) + + public static void ClearDirty(object entity) { IFieldInterceptor interceptor = ExtractFieldInterceptor(entity); if (interceptor != null) @@ -52,8 +52,8 @@ interceptor.ClearDirty(); } } - - public static void MarkDirty(object entity) + + public static void MarkDirty(object entity) { IFieldInterceptor interceptor = ExtractFieldInterceptor(entity); if (interceptor != null) Modified: trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -26,5 +26,8 @@ /// <summary> Clear the internal dirty flag.</summary> void ClearDirty(); + + /// <summary> Intercept field set/get </summary> + object Intercept(object target, string fieldName); } } \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -0,0 +1,7 @@ +namespace NHibernate.Intercept +{ + public interface IFieldInterceptorAccessor + { + IFieldInterceptor FieldInterceptor { get; set; } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-24 16:46:51 UTC (rev 4923) @@ -640,6 +640,8 @@ <Compile Include="Hql\Ast\ANTLR\Tree\UpdateStatement.cs" /> <Compile Include="Hql\Ast\HqlTreeBuilder.cs" /> <Compile Include="Hql\Ast\HqlTreeNode.cs" /> + <Compile Include="Intercept\DefaultFieldInterceptor.cs" /> + <Compile Include="Intercept\IFieldInterceptorAccessor.cs" /> <Compile Include="IQueryExpression.cs" /> <Compile Include="IQueryOver.cs" /> <Compile Include="Criterion\QueryOver.cs" /> Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1245,7 +1245,7 @@ // are shared PK one-to-one associations which are // handled differently in the Type#nullSafeGet code... ps = session.Batcher.PrepareCommand(CommandType.Text, lazySelect, IdentifierType.SqlTypes(Factory)); - IdentifierType.NullSafeSet(ps, id, 1, session); + IdentifierType.NullSafeSet(ps, id, 0, session); rs = session.Batcher.ExecuteReader(ps); rs.Read(); } Modified: trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using Iesi.Collections.Generic; using NHibernate.Engine; @@ -42,5 +43,10 @@ public abstract INHibernateProxy GetProxy(object id, ISessionImplementor session); + + public virtual object GetFieldInterceptionProxy() + { + throw new NotSupportedException(); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -5,48 +5,50 @@ namespace NHibernate.Proxy { - /// <summary> Contract for run-time, proxy-based lazy initialization proxies. </summary> - public interface IProxyFactory - { - /// <summary> Called immediately after instantiation of this factory. </summary> - /// <param name="entityName"> - /// The name of the entity for which this factory should generate proxies. - /// </param> - /// <param name="persistentClass"> - /// The entity class for which to generate proxies; not always the same as the entityName. - /// </param> - /// <param name="interfaces"> - /// The interfaces to expose in the generated proxy; - /// <see cref="INHibernateProxy"/> is already included in this collection. - /// </param> - /// <param name="getIdentifierMethod"> - /// Reference to the identifier getter method; invocation on this method should not force initialization - /// </param> - /// <param name="setIdentifierMethod"> - /// Reference to the identifier setter method; invocation on this method should not force initialization - /// </param> - /// <param name="componentIdType"> - /// For composite identifier types, a reference to - /// the <see cref="ComponentType">type</see> of the identifier - /// property; again accessing the id should generally not cause - /// initialization - but need to bear in mind key-many-to-one - /// mappings. - /// </param> - /// <exception cref="HibernateException"> Indicates a problem completing post </exception> - /// <remarks> - /// Essentially equivalent to constructor injection, but contracted - /// here via interface. - /// </remarks> - void PostInstantiate(string entityName, System.Type persistentClass, ISet<System.Type> interfaces, - MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType); + /// <summary> Contract for run-time, proxy-based lazy initialization proxies. </summary> + public interface IProxyFactory + { + /// <summary> Called immediately after instantiation of this factory. </summary> + /// <param name="entityName"> + /// The name of the entity for which this factory should generate proxies. + /// </param> + /// <param name="persistentClass"> + /// The entity class for which to generate proxies; not always the same as the entityName. + /// </param> + /// <param name="interfaces"> + /// The interfaces to expose in the generated proxy; + /// <see cref="INHibernateProxy"/> is already included in this collection. + /// </param> + /// <param name="getIdentifierMethod"> + /// Reference to the identifier getter method; invocation on this method should not force initialization + /// </param> + /// <param name="setIdentifierMethod"> + /// Reference to the identifier setter method; invocation on this method should not force initialization + /// </param> + /// <param name="componentIdType"> + /// For composite identifier types, a reference to + /// the <see cref="ComponentType">type</see> of the identifier + /// property; again accessing the id should generally not cause + /// initialization - but need to bear in mind key-many-to-one + /// mappings. + /// </param> + /// <exception cref="HibernateException"> Indicates a problem completing post </exception> + /// <remarks> + /// Essentially equivalent to constructor injection, but contracted + /// here via interface. + /// </remarks> + void PostInstantiate(string entityName, System.Type persistentClass, ISet<System.Type> interfaces, + MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType); - /// <summary> - /// Create a new proxy - /// </summary> - /// <param name="id">The id value for the proxy to be generated.</param> - /// <param name="session">The session to which the generated proxy will be associated.</param> - /// <returns>The generated proxy.</returns> - /// <exception cref="HibernateException">Indicates problems generating requested proxy.</exception> - INHibernateProxy GetProxy(object id, ISessionImplementor session); - } + /// <summary> + /// Create a new proxy + /// </summary> + /// <param name="id">The id value for the proxy to be generated.</param> + /// <param name="session">The session to which the generated proxy will be associated.</param> + /// <returns>The generated proxy.</returns> + /// <exception cref="HibernateException">Indicates problems generating requested proxy.</exception> + INHibernateProxy GetProxy(object id, ISessionImplementor session); + + object GetFieldInterceptionProxy(); + } } Modified: trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using Iesi.Collections.Generic; using NHibernate.Engine; @@ -23,6 +24,11 @@ return new MapProxy(new MapLazyInitializer(entityName, id, session)); } + public object GetFieldInterceptionProxy() + { + throw new NotSupportedException(); + } + #endregion } } Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -35,8 +35,6 @@ private readonly StandardProperty[] properties; - #region temporary - private readonly string[] propertyNames; private readonly IType[] propertyTypes; private readonly bool[] propertyLaziness; @@ -50,13 +48,12 @@ private readonly bool[] propertyVersionability; private readonly CascadeStyle[] cascadeStyles; - #endregion - private readonly IDictionary<string, int?> propertyIndexes = new Dictionary<string, int?>(); private readonly bool hasCollections; private readonly bool hasMutableProperties; private readonly bool hasLazyProperties; + private readonly int[] naturalIdPropertyNumbers; private bool lazy; @@ -106,8 +103,6 @@ properties = new StandardProperty[propertySpan]; List<int> naturalIdNumbers = new List<int>(); - #region temporary - propertyNames = new string[propertySpan]; propertyTypes = new IType[propertySpan]; propertyUpdateability = new bool[propertySpan]; @@ -121,9 +116,6 @@ propertyLaziness = new bool[propertySpan]; cascadeStyles = new CascadeStyle[propertySpan]; - #endregion - - int i = 0; int tempVersionProperty = NoVersionIndex; bool foundCascade = false; @@ -155,11 +147,11 @@ foundNonIdentifierPropertyNamedId = true; } - #region temporary - bool lazyProperty = prop.IsLazy && lazyAvailable; if (lazyProperty) + { hasLazy = true; + } propertyLaziness[i] = lazyProperty; propertyNames[i] = properties[i].Name; @@ -178,8 +170,6 @@ cascadeStyles[i] = properties[i].CascadeStyle; - #endregion - if (properties[i].IsLazy) { hasLazy = true; @@ -226,10 +216,22 @@ versionPropertyIndex = tempVersionProperty; hasLazyProperties = hasLazy; - if (hasLazyProperties) log.Info("lazy property fetching available for: " + name); - lazy = persistentClass.IsLazy && (!persistentClass.HasPocoRepresentation || !ReflectHelper.IsFinalClass(persistentClass.ProxyInterface)); + + if (hasLazy) + { + if (lazy == false) + { + log.WarnFormat("Disabled lazy properies fetching for {0} beacuse it does not support lazy at the entity level", name); + hasLazyProperties = false; + } + else + { + log.Info("lazy property fetching available for: " + name); + } + } + mutable = persistentClass.IsMutable; if (!persistentClass.IsAbstract.HasValue) Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -74,7 +74,11 @@ public override bool IsInstrumented { - get { return FieldInterceptionHelper.IsInstrumented(MappedClass); } + get { + return + EntityMetamodel.HasLazyProperties && + FieldInterceptionHelper.IsInstrumented(MappedClass); + } } public override System.Type MappedClass @@ -97,12 +101,12 @@ if (optimizer == null) { log.Debug("Create Instantiator without optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, null); + return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties); } else { log.Debug("Create Instantiator using optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer); + return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties); } } Modified: trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -4,6 +4,7 @@ using log4net; using NHibernate.Bytecode; using NHibernate.Mapping; +using NHibernate.Proxy; using NHibernate.Util; namespace NHibernate.Tuple @@ -19,6 +20,10 @@ [NonSerialized] private readonly IInstantiationOptimizer optimizer; + private readonly IProxyFactory proxyFactory; + + private readonly bool hasLazyProperties; + private readonly bool embeddedIdentifier; [NonSerialized] @@ -49,12 +54,14 @@ } } - public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer) + public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer, IProxyFactory proxyFactory, bool hasLazyProperties) { mappedClass = persistentClass.MappedClass; proxyInterface = persistentClass.ProxyInterface; embeddedIdentifier = persistentClass.HasEmbeddedIdentifier; this.optimizer = optimizer; + this.proxyFactory = proxyFactory; + this.hasLazyProperties = hasLazyProperties; try { @@ -81,29 +88,30 @@ { throw new InstantiationException("Cannot instantiate abstract class or interface: ", mappedClass); } - else if (optimizer != null) + if (hasLazyProperties) { + return proxyFactory.GetFieldInterceptionProxy(); + } + if (optimizer != null) + { return optimizer.CreateInstance(); } - else if (mappedClass.IsValueType) + if (mappedClass.IsValueType) { return Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(mappedClass, true); } - else if (constructor == null) + if (constructor == null) { throw new InstantiationException("No default constructor for entity: ", mappedClass); } - else + try { - try - { - return constructor.Invoke(null); - } - catch (Exception e) - { - throw new InstantiationException("Could not instantiate entity: ", e, mappedClass); - } + return constructor.Invoke(null); } + catch (Exception e) + { + throw new InstantiationException("Could not instantiate entity: ", e, mappedClass); + } } public bool IsInstance(object obj) Modified: trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -9,613 +9,628 @@ namespace NHibernate.Util { - /// <summary> - /// Helper class for Reflection related code. - /// </summary> - public static class ReflectHelper - { - private static readonly ILog log = LogManager.GetLogger(typeof(ReflectHelper)); + /// <summary> + /// Helper class for Reflection related code. + /// </summary> + public static class ReflectHelper + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReflectHelper)); - public const BindingFlags AnyVisibilityInstance = BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic; + public const BindingFlags AnyVisibilityInstance = BindingFlags.Instance | BindingFlags.Public | + BindingFlags.NonPublic; - private static readonly System.Type[] NoClasses = System.Type.EmptyTypes; + private static readonly System.Type[] NoClasses = System.Type.EmptyTypes; - private static readonly MethodInfo Exception_InternalPreserveStackTrace = - typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly MethodInfo Exception_InternalPreserveStackTrace = + typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); - /// <summary> - /// Determine if the specified <see cref="System.Type"/> overrides the - /// implementation of Equals from <see cref="Object"/> - /// </summary> - /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> - /// <returns><see langword="true" /> if any type in the hierarchy overrides Equals(object).</returns> - public static bool OverridesEquals(System.Type clazz) - { - return OverrideMethod(clazz, "Equals", new[] { typeof(object) }); - } + /// <summary> + /// Determine if the specified <see cref="System.Type"/> overrides the + /// implementation of Equals from <see cref="Object"/> + /// </summary> + /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> + /// <returns><see langword="true" /> if any type in the hierarchy overrides Equals(object).</returns> + public static bool OverridesEquals(System.Type clazz) + { + return OverrideMethod(clazz, "Equals", new[] { typeof(object) }); + } - private static bool OverrideMethod(System.Type clazz, string methodName, System.Type[] parametersTypes) - { - try - { - MethodInfo method = !clazz.IsInterface - ? clazz.GetMethod(methodName, parametersTypes) - : GetMethodFromInterface(clazz, methodName, parametersTypes); - if (method == null) - { - return false; - } - else - { - // make sure that the DeclaringType is not System.Object - if that is the - // declaring type then there is no override. - return !method.DeclaringType.Equals(typeof(object)); - } - } - catch (AmbiguousMatchException) - { - // an ambigious match means that there is an override and it - // can't determine which one to use. - return true; - } - } + private static bool OverrideMethod(System.Type clazz, string methodName, System.Type[] parametersTypes) + { + try + { + MethodInfo method = !clazz.IsInterface + ? clazz.GetMethod(methodName, parametersTypes) + : GetMethodFromInterface(clazz, methodName, parametersTypes); + if (method == null) + { + return false; + } + else + { + // make sure that the DeclaringType is not System.Object - if that is the + // declaring type then there is no override. + return !method.DeclaringType.Equals(typeof(object)); + } + } + catch (AmbiguousMatchException) + { + // an ambigious match means that there is an override and it + // can't determine which one to use. + return true; + } + } - private static MethodInfo GetMethodFromInterface(System.Type type, string methodName, System.Type[] parametersTypes) - { - const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; - if(type == null) - { - return null; - } - MethodInfo method = type.GetMethod(methodName, flags, null, parametersTypes, null); - if (method == null) - { - System.Type[] interfaces = type.GetInterfaces(); - foreach (var @interface in interfaces) - { - method = GetMethodFromInterface(@interface, methodName, parametersTypes); - if(method != null) - { - return method; - } - } - } - return method; - } + private static MethodInfo GetMethodFromInterface(System.Type type, string methodName, System.Type[] parametersTypes) + { + const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; + if (type == null) + { + return null; + } + MethodInfo method = type.GetMethod(methodName, flags, null, parametersTypes, null); + if (method == null) + { + System.Type[] interfaces = type.GetInterfaces(); + foreach (var @interface in interfaces) + { + method = GetMethodFromInterface(@interface, methodName, parametersTypes); + if (method != null) + { + return method; + } + } + } + return method; + } - /// <summary> - /// Determine if the specified <see cref="System.Type"/> overrides the - /// implementation of GetHashCode from <see cref="Object"/> - /// </summary> - /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> - /// <returns><see langword="true" /> if any type in the hierarchy overrides GetHashCode().</returns> - public static bool OverridesGetHashCode(System.Type clazz) - { - return OverrideMethod(clazz, "GetHashCode", System.Type.EmptyTypes); - } + /// <summary> + /// Determine if the specified <see cref="System.Type"/> overrides the + /// implementation of GetHashCode from <see cref="Object"/> + /// </summary> + /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> + /// <returns><see langword="true" /> if any type in the hierarchy overrides GetHashCode().</returns> + public static bool OverridesGetHashCode(System.Type clazz) + { + return OverrideMethod(clazz, "GetHashCode", System.Type.EmptyTypes); + } - /// <summary> - /// Finds the <see cref="IGetter"/> for the property in the <see cref="System.Type"/>. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> - /// <param name="propertyName">The name of the Property to find.</param> - /// <param name="propertyAccessorName">The name of the property access strategy.</param> - /// <returns>The <see cref="IGetter"/> to get the value of the Property.</returns> - /// <remarks> - /// This one takes a propertyAccessor name as we might know the correct strategy by now so we avoid Exceptions which are costly - /// </remarks> - public static IGetter GetGetter(System.Type theClass, string propertyName, string propertyAccessorName) - { - return PropertyAccessorFactory - .GetPropertyAccessor(propertyAccessorName) - .GetGetter(theClass, propertyName); - } + /// <summary> + /// Finds the <see cref="IGetter"/> for the property in the <see cref="System.Type"/>. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> + /// <param name="propertyName">The name of the Property to find.</param> + /// <param name="propertyAccessorName">The name of the property access strategy.</param> + /// <returns>The <see cref="IGetter"/> to get the value of the Property.</returns> + /// <remarks> + /// This one takes a propertyAccessor name as we might know the correct strategy by now so we avoid Exceptions which are costly + /// </remarks> + public static IGetter GetGetter(System.Type theClass, string propertyName, string propertyAccessorName) + { + return PropertyAccessorFactory + .GetPropertyAccessor(propertyAccessorName) + .GetGetter(theClass, propertyName); + } - /// <summary> - /// Get the NHibernate <see cref="IType" /> for the named property of the <see cref="System.Type"/>. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the Property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="access">The name of the property accessor for the property.</param> - /// <returns> - /// The NHibernate <see cref="IType"/> for the named property. - /// </returns> - public static IType ReflectedPropertyType(System.Type theClass, string name, string access) - { - System.Type propertyClass = ReflectedPropertyClass(theClass, name, access); + /// <summary> + /// Get the NHibernate <see cref="IType" /> for the named property of the <see cref="System.Type"/>. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the Property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="access">The name of the property accessor for the property.</param> + /// <returns> + /// The NHibernate <see cref="IType"/> for the named property. + /// </returns> + public static IType ReflectedPropertyType(System.Type theClass, string name, string access) + { + System.Type propertyClass = ReflectedPropertyClass(theClass, name, access); - System.Type heuristicClass = propertyClass; + System.Type heuristicClass = propertyClass; - if (propertyClass.IsGenericType - && propertyClass.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) - { - heuristicClass = propertyClass.GetGenericArguments()[0]; - } + if (propertyClass.IsGenericType + && propertyClass.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) + { + heuristicClass = propertyClass.GetGenericArguments()[0]; + } - return TypeFactory.HeuristicType(heuristicClass.AssemblyQualifiedName); - } + return TypeFactory.HeuristicType(heuristicClass.AssemblyQualifiedName); + } - /// <summary> - /// Get the <see cref="System.Type" /> for the named property of a type. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="access">The name of the property accessor for the property.</param> - /// <returns>The <see cref="System.Type" /> for the named property.</returns> - public static System.Type ReflectedPropertyClass(System.Type theClass, string name, string access) - { - return GetGetter(theClass, name, access).ReturnType; - } + /// <summary> + /// Get the <see cref="System.Type" /> for the named property of a type. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="access">The name of the property accessor for the property.</param> + /// <returns>The <see cref="System.Type" /> for the named property.</returns> + public static System.Type ReflectedPropertyClass(System.Type theClass, string name, string access) + { + return GetGetter(theClass, name, access).ReturnType; + } - /// <summary> - /// Get the <see cref="System.Type" /> for the named property of a type. - /// </summary> - /// <param name="className">The FullName to find the property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="accessorName">The name of the property accessor for the property.</param> - /// <returns>The <see cref="System.Type" /> for the named property.</returns> - public static System.Type ReflectedPropertyClass(string className, string name, string accessorName) - { - try - { - System.Type clazz = ClassForName(className); - return GetGetter(clazz, name, accessorName).ReturnType; - } - catch (Exception cnfe) - { - throw new MappingException(string.Format("class {0} not found while looking for property: {1}", className, name), cnfe); - } - } + /// <summary> + /// Get the <see cref="System.Type" /> for the named property of a type. + /// </summary> + /// <param name="className">The FullName to find the property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="accessorName">The name of the property accessor for the property.</param> + /// <returns>The <see cref="System.Type" /> for the named property.</returns> + public static System.Type ReflectedPropertyClass(string className, string name, string accessorName) + { + try + { + System.Type clazz = ClassForName(className); + return GetGetter(clazz, name, accessorName).ReturnType; + } + catch (Exception cnfe) + { + throw new MappingException(string.Format("class {0} not found while looking for property: {1}", className, name), cnfe); + } + } - /// <summary> - /// Returns a reference to the Type. - /// </summary> - /// <param name="name">The name of the class or a fully qualified name.</param> - /// <returns>The Type for the Class.</returns> - public static System.Type ClassForName(string name) - { - AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(name); - System.Type result = TypeFromAssembly(parsedName, true); - return result; - } + /// <summary> + /// Returns a reference to the Type. + /// </summary> + /// <param name="name">The name of the class or a fully qualified name.</param> + /// <returns>The Type for the Class.</returns> + public static System.Type ClassForName(string name) + { + AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(name); + System.Type result = TypeFromAssembly(parsedName, true); + return result; + } - /// <summary> - /// Load a System.Type given is't name. - /// </summary> - /// <param name="classFullName">The class FullName or AssemblyQualifiedName</param> - /// <returns>The System.Type</returns> - /// <remarks> - /// If the <paramref name="classFullName"/> don't represent an <see cref="System.Type.AssemblyQualifiedName"/> - /// the method try to find the System.Type scanning all Assemblies of the <see cref="AppDomain.CurrentDomain"/>. - /// </remarks> - /// <exception cref="TypeLoadException">If no System.Type was found for <paramref name="classFullName"/>.</exception> - public static System.Type ClassForFullName(string classFullName) - { - System.Type result = null; - AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(classFullName); - if (!string.IsNullOrEmpty(parsedName.Assembly)) - { - result = TypeFromAssembly(parsedName, false); - } - else - { - if (!string.IsNullOrEmpty(classFullName)) - { - Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly a in ass) - { - result = a.GetType(classFullName, false, false); - if (result != null) - break; //<<<<<================ - } - } - } - if (result == null) - { - string message = "Could not load type " + classFullName + ". Possible cause: the assembly was not loaded or not specified."; - throw new TypeLoadException(message); - } + /// <summary> + /// Load a System.Type given is't name. + /// </summary> + /// <param name="classFullName">The class FullName or AssemblyQualifiedName</param> + /// <returns>The System.Type</returns> + /// <remarks> + /// If the <paramref name="classFullName"/> don't represent an <see cref="System.Type.AssemblyQualifiedName"/> + /// the method try to find the System.Type scanning all Assemblies of the <see cref="AppDomain.CurrentDomain"/>. + /// </remarks> + /// <exception cref="TypeLoadException">If no System.Type was found for <paramref name="classFullName"/>.</exception> + public static System.Type ClassForFullName(string classFullName) + { + System.Type result = null; + AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(classFullName); + if (!string.IsNullOrEmpty(parsedName.Assembly)) + { + result = TypeFromAssembly(parsedName, false); + } + else + { + if (!string.IsNullOrEmpty(classFullName)) + { + Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly a in ass) + { + result = a.GetType(classFullName, false, false); + if (result != null) + break; //<<<<<================ + } + } + } + if (result == null) + { + string message = "Could not load type " + classFullName + ". Possible cause: the assembly was not loaded or not specified."; + throw new TypeLoadException(message); + } - return result; - } + return result; + } - public static System.Type TypeFromAssembly(string type, string assembly, bool throwIfError) - { - return TypeFromAssembly(new AssemblyQualifiedTypeName(type, assembly), throwIfError); - } + public static System.Type TypeFromAssembly(string type, string assembly, bool throwIfError) + { + return TypeFromAssembly(new AssemblyQualifiedTypeName(type, assembly), throwIfError); + } - /// <summary> - /// Returns a <see cref="System.Type"/> from an already loaded Assembly or an - /// Assembly that is loaded with a partial name. - /// </summary> - /// <param name="name">An <see cref="AssemblyQualifiedTypeName" />.</param> - /// <param name="throwOnError"><see langword="true" /> if an exception should be thrown - /// in case of an error, <see langword="false" /> otherwise.</param> - /// <returns> - /// A <see cref="System.Type"/> object that represents the specified type, - /// or <see langword="null" /> if the type cannot be loaded. - /// </returns> - /// <remarks> - /// Attempts to get a reference to the type from an already loaded assembly. If the - /// type cannot be found then the assembly is loaded using - /// <see cref="Assembly.Load(string)" />. - /// </remarks> - public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError) - { - try - { - // Try to get the type from an already loaded assembly - System.Type type = System.Type.GetType(name.ToString()); + /// <summary> + /// Returns a <see cref="System.Type"/> from an already loaded Assembly or an + /// Assembly that is loaded with a partial name. + /// </summary> + /// <param name="name">An <see cref="AssemblyQualifiedTypeName" />.</param> + /// <param name="throwOnError"><see langword="true" /> if an exception should be thrown + /// in case of an error, <see langword="false" /> otherwise.</param> + /// <returns> + /// A <see cref="System.Type"/> object that represents the specified type, + /// or <see langword="null" /> if the type cannot be loaded. + /// </returns> + /// <remarks> + /// Attempts to get a reference to the type from an already loaded assembly. If the + /// type cannot be found then the assembly is loaded using + /// <see cref="Assembly.Load(string)" />. + /// </remarks> + public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError) + { + try + { + // Try to get the type from an already loaded assembly + System.Type type = System.Type.GetType(name.ToString()); - if (type != null) - { - return type; - } + if (type != null) + { + return type; + } - if (name.Assembly == null) - { - // No assembly was specified for the type, so just fail - string message = "Could not load type " + name + ". Possible cause: no assembly name specified."; - log.Warn(message); - if (throwOnError) throw new TypeLoadException(message); - return null; - } + if (name.Assembly == null) + { + // No assembly was specified for the type, so just fail + string message = "Could not load type " + name + ". Possible cause: no assembly name specified."; + log.Warn(message); + if (throwOnError) throw new TypeLoadException(message); + return null; + } - Assembly assembly = Assembly.Load(name.Assembly); + Assembly assembly = Assembly.Load(name.Assembly); - if (assembly == null) - { - log.Warn("Could not load type " + name + ". Possible cause: incorrect assembly name specified."); - return null; - } + if (assembly == null) + { + log.Warn("Could not load type " + name + ". Possible cause: incorrect assembly name specified."); + return null; + } - type = assembly.GetType(name.Type, throwOnError); + type = assembly.GetType(name.Type, throwOnError); - if (type == null) - { - log.Warn("Could not load type " + name + "."); - return null; - } + if (type == null) + { + log.Warn("Could not load type " + name + "."); + return null; + } - return type; - } - catch (Exception e) - { - if (log.IsErrorEnabled) - { - log.Error("Could not load type " + name + ".", e); - } - if (throwOnError) throw; - return null; - } - } + return type; + } + catch (Exception e) + { + ... [truncated message content] |
From: <aye...@us...> - 2010-01-22 14:04:13
|
Revision: 4922 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4922&view=rev Author: ayenderahien Date: 2010-01-22 14:04:02 +0000 (Fri, 22 Jan 2010) Log Message: ----------- Creating branch for lazy prop Modified Paths: -------------- branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmAny.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmArray.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmBag.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmList.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmMap.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/HbmSet.cs branches/LazyProps/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs branches/LazyProps/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs branches/LazyProps/src/NHibernate/Engine/StatefulPersistenceContext.cs branches/LazyProps/src/NHibernate/Intercept/FieldInterceptionHelper.cs branches/LazyProps/src/NHibernate/Mapping/PersistentClass.cs branches/LazyProps/src/NHibernate/NHibernate.csproj branches/LazyProps/src/NHibernate/Proxy/AbstractProxyFactory.cs branches/LazyProps/src/NHibernate/Proxy/IProxyFactory.cs branches/LazyProps/src/NHibernate/Proxy/Map/MapProxyFactory.cs branches/LazyProps/src/NHibernate/Tuple/Entity/AbstractEntityTuplizer.cs branches/LazyProps/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs branches/LazyProps/src/NHibernate/Tuple/PocoInstantiator.cs branches/LazyProps/src/NHibernate.ByteCode.Castle/NHibernate.ByteCode.Castle.csproj branches/LazyProps/src/NHibernate.ByteCode.Castle/ProxyFactory.cs branches/LazyProps/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs branches/LazyProps/src/NHibernate.ByteCode.LinFu/NHibernate.ByteCode.LinFu.csproj branches/LazyProps/src/NHibernate.ByteCode.LinFu/ProxyFactory.cs branches/LazyProps/src/NHibernate.Test/App.config branches/LazyProps/src/NHibernate.sln Added Paths: ----------- branches/LazyProps/ branches/LazyProps/src/NHibernate/Cfg/Configuration.cs branches/LazyProps/src/NHibernate/Event/Default/OnLockVisitor.cs branches/LazyProps/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs branches/LazyProps/src/NHibernate.ByteCode.Castle/LazyPropertyInterceptor.cs branches/LazyProps/src/NHibernate.ByteCode.LinFu/FieldInterceptor.cs branches/LazyProps/src/NHibernate.Test/FilterTest/ConfigFixture.cs branches/LazyProps/src/NHibernate.Test/HQL/Ast/HqlFixture.cs branches/LazyProps/src/NHibernate.Test/NHSpecificTest/LazyProperties/ branches/LazyProps/src/NHibernate.Test/NHSpecificTest/LazyProperties/Fixture.cs branches/LazyProps/src/NHibernate.Test/NHSpecificTest/LazyProperties/Mappings.hbm.xml branches/LazyProps/src/NHibernate.Test/NHSpecificTest/LazyProperties/Model.cs branches/LazyProps/src/NHibernate.Test/NHSpecificTest/NH2065/ branches/LazyProps/src/NHibernate.Test/NHibernate.Test.csproj Removed Paths: ------------- branches/LazyProps/src/NHibernate/Cfg/Configuration.cs branches/LazyProps/src/NHibernate/Event/Default/OnLockVisitor.cs branches/LazyProps/src/NHibernate.Test/FilterTest/ConfigFixture.cs branches/LazyProps/src/NHibernate.Test/HQL/Ast/HqlFixture.cs branches/LazyProps/src/NHibernate.Test/NHibernate.Test.csproj Property changes on: branches/LazyProps ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: svn:ignore + build Added: bugtraq:logregex + NH-\d+ Added: svn:mergeinfo + /branches/2.1.x/nhibernate:4690-4691,4696-4697,4711,4715-4716,4905-4908 Deleted: branches/LazyProps/src/NHibernate/Cfg/Configuration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2010-01-10 19:01:42 UTC (rev 4916) +++ branches/LazyProps/src/NHibernate/Cfg/Configuration.cs 2010-01-22 14:04:02 UTC (rev 4922) @@ -1,2292 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Configuration; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Text; -using System.Xml; -using System.Xml.Schema; -using Iesi.Collections; -using Iesi.Collections.Generic; -using log4net; -using NHibernate.Bytecode; -using NHibernate.Cfg.ConfigurationSchema; -using NHibernate.Cfg.MappingSchema; -using NHibernate.Cfg.XmlHbmBinding; -using NHibernate.Dialect; -using NHibernate.Dialect.Function; -using NHibernate.Dialect.Schema; -using NHibernate.Engine; -using NHibernate.Event; -using NHibernate.Id; -using NHibernate.Impl; -using NHibernate.Mapping; -using NHibernate.Proxy; -using NHibernate.Tool.hbm2ddl; -using NHibernate.Type; -using NHibernate.Util; -using Array=System.Array; -using System.Runtime.Serialization; - -namespace NHibernate.Cfg -{ - /// <summary> - /// Allows the application to specify properties and mapping documents to be used when creating - /// a <see cref="ISessionFactory" />. - /// </summary> - /// <remarks> - /// <para> - /// Usually an application will create a single <see cref="Configuration" />, build a single instance - /// of <see cref="ISessionFactory" />, and then instantiate <see cref="ISession"/> objects in threads - /// servicing client requests. - /// </para> - /// <para> - /// The <see cref="Configuration" /> is meant only as an initialization-time object. <see cref="ISessionFactory" /> - /// is immutable and does not retain any association back to the <see cref="Configuration" /> - /// </para> - /// </remarks> - [Serializable] - public class Configuration:ISerializable - { - /// <summary>Default name for hibernate configuration file.</summary> - public const string DefaultHibernateCfgFileName = "hibernate.cfg.xml"; - - private string currentDocumentName; - private bool preMappingBuildProcessed; - - protected IDictionary<string, PersistentClass> classes; // entityName, PersistentClass - protected IDictionary<string, NHibernate.Mapping.Collection> collections; - protected IDictionary<string, Table> tables; - protected IList<SecondPassCommand> secondPasses; - protected Queue<FilterSecondPassArgs> filtersSecondPasses; - protected IList<Mappings.PropertyReference> propertyReferences; - private IInterceptor interceptor; - private IDictionary<string, string> properties; - protected IList<IAuxiliaryDatabaseObject> auxiliaryDatabaseObjects; - - private INamingStrategy namingStrategy = DefaultNamingStrategy.Instance; - private MappingsQueue mappingsQueue; - - private EventListeners eventListeners; - protected IDictionary<string, TypeDef> typeDefs; - protected ISet<ExtendsQueueEntry> extendsQueue; - protected IDictionary<string, Mappings.TableDescription> tableNameBinding; - protected IDictionary<Table, Mappings.ColumnNames> columnNameBindingPerTable; - - private static readonly ILog log = LogManager.GetLogger(typeof (Configuration)); - - - protected internal SettingsFactory settingsFactory; - - #region ISerializable Members - public Configuration(SerializationInfo info, StreamingContext context) - { - Reset(); - - EntityNotFoundDelegate = GetSerialedObject<IEntityNotFoundDelegate>(info, "entityNotFoundDelegate"); - - auxiliaryDatabaseObjects = GetSerialedObject<IList<IAuxiliaryDatabaseObject>>(info, "auxiliaryDatabaseObjects"); - classes = GetSerialedObject<IDictionary<string, PersistentClass>>(info, "classes"); - collections = GetSerialedObject<IDictionary<string, NHibernate.Mapping.Collection>>(info, "collections"); - - columnNameBindingPerTable = GetSerialedObject<IDictionary<Table, Mappings.ColumnNames>>(info, - "columnNameBindingPerTable"); - defaultAssembly = GetSerialedObject<string>(info, "defaultAssembly"); - defaultNamespace = GetSerialedObject<string>(info, "defaultNamespace"); - eventListeners = GetSerialedObject<EventListeners>(info, "eventListeners"); - //this.extendsQueue = GetSerialedObject<ISet<ExtendsQueueEntry>>(info, "extendsQueue"); - FilterDefinitions = GetSerialedObject<IDictionary<string, FilterDefinition>>(info, "filterDefinitions"); - Imports = GetSerialedObject<IDictionary<string, string>>(info, "imports"); - interceptor = GetSerialedObject<IInterceptor>(info, "interceptor"); - mapping = GetSerialedObject<IMapping>(info, "mapping"); - NamedQueries = GetSerialedObject<IDictionary<string, NamedQueryDefinition>>(info, "namedQueries"); - NamedSQLQueries = GetSerialedObject<IDictionary<string, NamedSQLQueryDefinition>>(info, "namedSqlQueries"); - namingStrategy = GetSerialedObject<INamingStrategy>(info, "namingStrategy"); - properties = GetSerialedObject<IDictionary<string, string>>(info, "properties"); - propertyReferences = GetSerialedObject<IList<Mappings.PropertyReference>>(info, "propertyReferences"); - settingsFactory = GetSerialedObject<SettingsFactory>(info, "settingsFactory"); - SqlFunctions = GetSerialedObject<IDictionary<string, ISQLFunction>>(info, "sqlFunctions"); - SqlResultSetMappings = GetSerialedObject<IDictionary<string, ResultSetMappingDefinition>>(info, - "sqlResultSetMappings"); - tableNameBinding = GetSerialedObject<IDictionary<string, Mappings.TableDescription>>(info, "tableNameBinding"); - tables = GetSerialedObject<IDictionary<string, Table>>(info, "tables"); - typeDefs = GetSerialedObject<IDictionary<string, TypeDef>>(info, "typeDefs"); - filtersSecondPasses = GetSerialedObject<Queue<FilterSecondPassArgs>>(info, "filtersSecondPasses"); - } - - private T GetSerialedObject<T>(SerializationInfo info, string name) - { - return (T)info.GetValue(name, typeof(T)); - } - - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - ConfigureProxyFactoryFactory(); - SecondPassCompile(); - Validate(); - - info.AddValue("entityNotFoundDelegate", EntityNotFoundDelegate); - - info.AddValue("auxiliaryDatabaseObjects", auxiliaryDatabaseObjects); - info.AddValue("classes", classes); - info.AddValue("collections", collections); - info.AddValue("columnNameBindingPerTable", columnNameBindingPerTable); - info.AddValue("defaultAssembly", defaultAssembly); - info.AddValue("defaultNamespace", defaultNamespace); - info.AddValue("eventListeners", eventListeners); - //info.AddValue("extendsQueue", this.extendsQueue); - info.AddValue("filterDefinitions", FilterDefinitions); - info.AddValue("imports", Imports); - info.AddValue("interceptor", interceptor); - info.AddValue("mapping", mapping); - info.AddValue("namedQueries", NamedQueries); - info.AddValue("namedSqlQueries", NamedSQLQueries); - info.AddValue("namingStrategy", namingStrategy); - info.AddValue("properties", properties); - info.AddValue("propertyReferences", propertyReferences); - info.AddValue("settingsFactory", settingsFactory); - info.AddValue("sqlFunctions", SqlFunctions); - info.AddValue("sqlResultSetMappings", SqlResultSetMappings); - info.AddValue("tableNameBinding", tableNameBinding); - info.AddValue("tables", tables); - info.AddValue("typeDefs", typeDefs); - info.AddValue("filtersSecondPasses", filtersSecondPasses); - } - #endregion - - /// <summary> - /// Clear the internal state of the <see cref="Configuration"/> object. - /// </summary> - protected void Reset() - { - classes = new Dictionary<string, PersistentClass>(); //new SequencedHashMap(); - to make NH-369 bug deterministic - Imports = new Dictionary<string, string>(); - collections = new Dictionary<string, NHibernate.Mapping.Collection>(); - tables = new Dictionary<string, Table>(); - NamedQueries = new Dictionary<string, NamedQueryDefinition>(); - NamedSQLQueries = new Dictionary<string, NamedSQLQueryDefinition>(); - SqlResultSetMappings = new Dictionary<string, ResultSetMappingDefinition>(); - secondPasses = new List<SecondPassCommand>(); - propertyReferences = new List<Mappings.PropertyReference>(); - FilterDefinitions = new Dictionary<string, FilterDefinition>(); - interceptor = emptyInterceptor; - properties = Environment.Properties; - auxiliaryDatabaseObjects = new List<IAuxiliaryDatabaseObject>(); - SqlFunctions = new Dictionary<string, ISQLFunction>(); - mappingsQueue = new MappingsQueue(); - eventListeners = new EventListeners(); - typeDefs = new Dictionary<string, TypeDef>(); - extendsQueue = new HashedSet<ExtendsQueueEntry>(); - tableNameBinding = new Dictionary<string, Mappings.TableDescription>(); - columnNameBindingPerTable = new Dictionary<Table, Mappings.ColumnNames>(); - filtersSecondPasses = new Queue<FilterSecondPassArgs>(); - } - [Serializable] - private class Mapping : IMapping - { - private readonly Configuration configuration; - - public Mapping(Configuration configuration) - { - this.configuration = configuration; - } - - private PersistentClass GetPersistentClass(string className) - { - PersistentClass pc = configuration.classes[className]; - if (pc == null) - { - throw new MappingException("persistent class not known: " + className); - } - return pc; - } - - public IType GetIdentifierType(string className) - { - return GetPersistentClass(className).Identifier.Type; - } - - public string GetIdentifierPropertyName(string className) - { - PersistentClass pc = GetPersistentClass(className); - if (!pc.HasIdentifierProperty) - { - return null; - } - return pc.IdentifierProperty.Name; - } - - public IType GetReferencedPropertyType(string className, string propertyName) - { - PersistentClass pc = GetPersistentClass(className); - Property prop = pc.GetProperty(propertyName); - - if (prop == null) - { - throw new MappingException("property not known: " + pc.MappedClass.FullName + '.' + propertyName); - } - return prop.Type; - } - - public bool HasNonIdentifierPropertyNamedId(string className) - { - return "id".Equals(GetIdentifierPropertyName(className)); - } - } - - private IMapping mapping; - - protected Configuration(SettingsFactory settingsFactory) - { - InitBlock(); - this.settingsFactory = settingsFactory; - Reset(); - } - - private void InitBlock() - { - mapping = BuildMapping(); - } - - public virtual IMapping BuildMapping() - { - return new Mapping(this); - } - - /// <summary> - /// Create a new Configuration object. - /// </summary> - public Configuration() : this(new SettingsFactory()) {} - - /// <summary> - /// The class mappings - /// </summary> - public ICollection<PersistentClass> ClassMappings - { - get { return classes.Values; } - } - - /// <summary> - /// The collection mappings - /// </summary> - public ICollection<NHibernate.Mapping.Collection> CollectionMappings - { - get { return collections.Values; } - } - - /// <summary> - /// The table mappings - /// </summary> - private ICollection<Table> TableMappings - { - get { return tables.Values; } - } - - /// <summary> - /// Get the mapping for a particular class - /// </summary> - public PersistentClass GetClassMapping(System.Type persistentClass) - { - // TODO NH: Remove this method - return GetClassMapping(persistentClass.FullName); - } - - /// <summary> Get the mapping for a particular entity </summary> - /// <param name="entityName">An entity name. </param> - /// <returns> the entity mapping information </returns> - public PersistentClass GetClassMapping(string entityName) - { - PersistentClass result; - classes.TryGetValue(entityName, out result); - return result; - } - - /// <summary> - /// Get the mapping for a particular collection role - /// </summary> - /// <param name="role">a collection role</param> - /// <returns><see cref="NHibernate.Mapping.Collection" /></returns> - public NHibernate.Mapping.Collection GetCollectionMapping(string role) - { - return collections.ContainsKey(role) ? collections[role] : null; - } - - /// <summary> - /// Read mappings from a particular XML file. This method is equivalent - /// to <see cref="AddXmlFile(string)" />. - /// </summary> - /// <param name="xmlFile"></param> - /// <returns></returns> - public Configuration AddFile(string xmlFile) - { - return AddXmlFile(xmlFile); - } - - public Configuration AddFile(FileInfo xmlFile) - { - return AddFile(xmlFile.FullName); - } - - private static void LogAndThrow(Exception exception) - { - if (log.IsErrorEnabled) - { - log.Error(exception.Message, exception); - } - - throw exception; - } - - /// <summary> - /// Read mappings from a particular XML file. - /// </summary> - /// <param name="xmlFile">a path to a file</param> - /// <returns>This configuration object.</returns> - public Configuration AddXmlFile(string xmlFile) - { - log.Info("Mapping file: " + xmlFile); - XmlTextReader textReader = null; - try - { - textReader = new XmlTextReader(xmlFile); - AddXmlReader(textReader, xmlFile); - } - catch (MappingException) - { - throw; - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not configure datastore from file " + xmlFile, e)); - } - finally - { - if (textReader != null) - { - textReader.Close(); - } - } - return this; - } - - public Configuration AddXml(string xml) - { - return AddXml(xml, "(string)"); - } - - /// <summary> - /// Read mappings from a <see cref="string" />. This method is equivalent to - /// <see cref="AddXmlString(string)" />. - /// </summary> - /// <param name="xml">an XML string</param> - /// <param name="name">The name to use in error reporting. May be <see langword="null" />.</param> - /// <returns>This configuration object.</returns> - public Configuration AddXml(string xml, string name) - { - if (log.IsDebugEnabled) - { - log.Debug("Mapping XML:\n" + xml); - } - XmlTextReader reader = null; - try - { - reader = new XmlTextReader(xml, XmlNodeType.Document, null); - // make a StringReader for the string passed in - the StringReader - // inherits from TextReader. We can use the XmlTextReader.ctor that - // takes the TextReader to build from a string... - AddXmlReader(reader, name); - } - catch (MappingException) - { - throw; - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not configure datastore from XML string " + name, e)); - } - finally - { - if (reader != null) - { - reader.Close(); - } - } - return this; - } - - /// <summary> - /// Read mappings from a <see cref="string" />. - /// </summary> - /// <param name="xml">an XML string</param> - /// <returns>This configuration object.</returns> - public Configuration AddXmlString(string xml) - { - return AddXml(xml); - } - - /// <summary> - /// Read mappings from a URL. - /// </summary> - /// <param name="url">a URL</param> - /// <returns>This configuration object.</returns> - public Configuration AddUrl(string url) - { - // AddFile works for URLs currently - return AddFile(url); - } - - /// <summary> - /// Read mappings from a URL. - /// </summary> - /// <param name="url">a <see cref="Uri" /> to read the mappings from.</param> - /// <returns>This configuration object.</returns> - public Configuration AddUrl(Uri url) - { - return AddUrl(url.AbsolutePath); - } - - public Configuration AddDocument(XmlDocument doc) - { - return AddDocument(doc, "(XmlDocument)"); - } - - /// <summary> - /// Read mappings from an <see cref="XmlDocument" />. - /// </summary> - /// <param name="doc">A loaded <see cref="XmlDocument" /> that contains the mappings.</param> - /// <param name="name">The name of the document, for error reporting purposes.</param> - /// <returns>This configuration object.</returns> - public Configuration AddDocument(XmlDocument doc, string name) - { - if (log.IsDebugEnabled) - { - log.Debug("Mapping XML:\n" + doc.OuterXml); - } - - try - { - using (var ms = new MemoryStream()) - { - doc.Save(ms); - ms.Position = 0; - AddInputStream(ms, name); - } - return this; - } - catch (MappingException) - { - throw; - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not configure datastore from XML document " + name, e)); - return this; // To please the compiler - } - } - - /// <summary> - /// Takes the validated XmlDocument and has the Binder do its work of - /// creating Mapping objects from the Mapping Xml. - /// </summary> - /// <param name="doc">The NamedXmlDocument that contains the <b>validated</b> mapping XML file.</param> - private void AddValidatedDocument(NamedXmlDocument doc) - { - AddDeserializedMapping(doc.Document, doc.Name); - } - - /// <summary> - /// Add mapping data using deserialized class. - /// </summary> - /// <param name="mappingDocument">Mapping metadata.</param> - /// <param name="documentFileName">XML file's name where available; otherwise null.</param> - public void AddDeserializedMapping(HbmMapping mappingDocument, string documentFileName) - { - if (mappingDocument == null) - { - throw new ArgumentNullException("mappingDocument"); - } - try - { - Dialect.Dialect dialect = Dialect.Dialect.GetDialect(properties); - Mappings mappings = CreateMappings(dialect); - - new MappingRootBinder(mappings, dialect).Bind(mappingDocument); - } - catch (Exception e) - { - var message = documentFileName == null - ? "Could not compile deserialized mapping document." - : "Could not compile the mapping document: " + documentFileName; - LogAndThrow(new MappingException(message, e)); - } - } - - /// <summary> - /// Create a new <see cref="Mappings" /> to add classes and collection - /// mappings to. - /// </summary> - public Mappings CreateMappings(Dialect.Dialect dialect) - { - ProcessPreMappingBuildProperties(); - return new Mappings(classes, collections, tables, NamedQueries, NamedSQLQueries, SqlResultSetMappings, Imports, - secondPasses, filtersSecondPasses, propertyReferences, namingStrategy, typeDefs, FilterDefinitions, extendsQueue, - auxiliaryDatabaseObjects, tableNameBinding, columnNameBindingPerTable, defaultAssembly, - defaultNamespace, dialect); - } - - private void ProcessPreMappingBuildProperties() - { - if(preMappingBuildProcessed) - { - return; - } - ConfigureCollectionTypeFactory(); - preMappingBuildProcessed = true; - } - - private void ConfigureCollectionTypeFactory() - { - var ctfc = GetProperty(Environment.CollectionTypeFactoryClass); - if(string.IsNullOrEmpty(ctfc)) - { - return; - } - var ictfc = Environment.BytecodeProvider as IInjectableCollectionTypeFactoryClass; - if(ictfc == null) - { - return; - } - ictfc.SetCollectionTypeFactoryClass(ctfc); - } - - /// <summary> - /// Read mappings from a <see cref="Stream" />. - /// </summary> - /// <param name="xmlInputStream">The stream containing XML</param> - /// <returns>This Configuration object.</returns> - /// <remarks> - /// The <see cref="Stream"/> passed in through the parameter <paramref name="xmlInputStream" /> - /// is not <em>guaranteed</em> to be cleaned up by this method. It is the caller's responsiblity to - /// ensure that <paramref name="xmlInputStream" /> is properly handled when this method - /// completes. - /// </remarks> - public Configuration AddInputStream(Stream xmlInputStream) - { - return AddInputStream(xmlInputStream, null); - } - - /// <summary> - /// Read mappings from a <see cref="Stream" />. - /// </summary> - /// <param name="xmlInputStream">The stream containing XML</param> - /// <param name="name">The name of the stream to use in error reporting. May be <see langword="null" />.</param> - /// <returns>This Configuration object.</returns> - /// <remarks> - /// The <see cref="Stream"/> passed in through the parameter <paramref name="xmlInputStream" /> - /// is not <em>guaranteed</em> to be cleaned up by this method. It is the caller's responsiblity to - /// ensure that <paramref name="xmlInputStream" /> is properly handled when this method - /// completes. - /// </remarks> - public Configuration AddInputStream(Stream xmlInputStream, string name) - { - XmlTextReader textReader = null; - try - { - textReader = new XmlTextReader(xmlInputStream); - AddXmlReader(textReader, name); - return this; - } - catch (MappingException) - { - throw; - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not configure datastore from input stream " + name, e)); - return this; // To please the compiler - } - finally - { - if (textReader != null) - { - textReader.Close(); - } - } - } - - /// <summary> - /// Adds the mappings in the resource of the assembly. - /// </summary> - /// <param name="path">The path to the resource file in the assembly.</param> - /// <param name="assembly">The assembly that contains the resource file.</param> - /// <returns>This configuration object.</returns> - public Configuration AddResource(string path, Assembly assembly) - { - string debugName = path; - log.Info("Mapping resource: " + debugName); - Stream rsrc = assembly.GetManifestResourceStream(path); - if (rsrc == null) - { - LogAndThrow(new MappingException("Resource not found: " + debugName)); - } - - try - { - return AddInputStream(rsrc, debugName); - } - catch (MappingException) - { - throw; - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not configure datastore from resource " + debugName, e)); - return this; // To please the compiler - } - finally - { - if (rsrc != null) - { - rsrc.Close(); - } - } - } - - /// <summary> - /// Adds the mappings from ebedded resources of the assembly. - /// </summary> - /// <param name="paths">Paths to the resource files in the assembly.</param> - /// <param name="assembly">The assembly that contains the resource files.</param> - /// <returns>This configuration object.</returns> - public Configuration AddResources(IEnumerable<string> paths, Assembly assembly) - { - if (paths == null) - { - throw new ArgumentNullException("paths"); - } - foreach (var path in paths) - { - AddResource(path, assembly); - } - return this; - } - - /// <summary> - /// Read a mapping from an embedded resource, using a convention. - /// </summary> - /// <param name="persistentClass">The type to map.</param> - /// <returns>This configuration object.</returns> - /// <remarks> - /// The convention is for class <c>Foo.Bar.Foo</c> to be mapped by - /// the resource named <c>Foo.Bar.Foo.hbm.xml</c>, embedded in - /// the class' assembly. If the mappings and classes are defined - /// in different assemblies or don't follow the naming convention, - /// this method cannot be used. - /// </remarks> - public Configuration AddClass(System.Type persistentClass) - { - return AddResource(persistentClass.FullName + ".hbm.xml", persistentClass.Assembly); - } - - /// <summary> - /// Adds all of the assembly's embedded resources whose names end with <c>.hbm.xml</c>. - /// </summary> - /// <param name="assemblyName">The name of the assembly to load.</param> - /// <returns>This configuration object.</returns> - /// <remarks> - /// The assembly must be loadable using <see cref="Assembly.Load(string)" />. If this - /// condition is not satisfied, load the assembly manually and call - /// <see cref="AddAssembly(Assembly)"/> instead. - /// </remarks> - public Configuration AddAssembly(string assemblyName) - { - log.Info("Searching for mapped documents in assembly: " + assemblyName); - - Assembly assembly = null; - try - { - assembly = Assembly.Load(assemblyName); - } - catch (Exception e) - { - LogAndThrow(new MappingException("Could not add assembly " + assemblyName, e)); - } - - return AddAssembly(assembly); - } - - /// <summary> - /// Adds all of the assembly's embedded resources whose names end with <c>.hbm.xml</c>. - /// </summary> - /// <param name="assembly">The assembly.</param> - /// <returns>This configuration object.</returns> - public Configuration AddAssembly(Assembly assembly) - { - IList<string> resourceNames = GetAllHbmXmlResourceNames(assembly); - if (resourceNames.Count == 0) - { - log.Warn("No mapped documents found in assembly: " + assembly.FullName); - } - foreach (var name in resourceNames) - { - AddResource(name, assembly); - } - return this; - } - - private static IList<string> GetAllHbmXmlResourceNames(Assembly assembly) - { - var result = new List<string>(); - - foreach (var resource in assembly.GetManifestResourceNames()) - { - if (resource.EndsWith(".hbm.xml")) - { - result.Add(resource); - } - } - - return result; - } - - /// <summary> - /// Read all mapping documents from a directory tree. Assume that any - /// file named <c>*.hbm.xml</c> is a mapping document. - /// </summary> - /// <param name="dir">a directory</param> - public Configuration AddDirectory(DirectoryInfo dir) - { - foreach (var subDirectory in dir.GetDirectories()) - { - AddDirectory(subDirectory); - } - - foreach (var hbmXml in dir.GetFiles("*.hbm.xml")) - { - AddFile(hbmXml); - } - - return this; - } - - /// <summary> - /// Generate DDL for dropping tables - /// </summary> - /// <seealso cref="NHibernate.Tool.hbm2ddl.SchemaExport" /> - public string[] GenerateDropSchemaScript(Dialect.Dialect dialect) - { - SecondPassCompile(); - - string defaultCatalog = PropertiesHelper.GetString(Environment.DefaultCatalog, properties, null); - string defaultSchema = PropertiesHelper.GetString(Environment.DefaultSchema, properties, null); - - var script = new List<string>(); - - // drop them in reverse order in case db needs it done that way... - for (int i = auxiliaryDatabaseObjects.Count - 1; i >= 0; i--) - { - IAuxiliaryDatabaseObject auxDbObj = auxiliaryDatabaseObjects[i]; - if (auxDbObj.AppliesToDialect(dialect)) - { - script.Add(auxDbObj.SqlDropString(dialect, defaultCatalog, defaultSchema)); - } - } - - if (dialect.DropConstraints) - { - foreach (var table in TableMappings) - { - if (table.IsPhysicalTable && IncludeAction(table.SchemaActions, SchemaAction.Drop)) - { - foreach (var fk in table.ForeignKeyIterator) - { - if (fk.HasPhysicalConstraint && IncludeAction(fk.ReferencedTable.SchemaActions, SchemaAction.Drop)) - { - script.Add(fk.SqlDropString(dialect, defaultCatalog, defaultSchema)); - } - } - } - } - } - - foreach (var table in TableMappings) - { - if (table.IsPhysicalTable && IncludeAction(table.SchemaActions, SchemaAction.Drop)) - { - script.Add(table.SqlDropString(dialect, defaultCatalog, defaultSchema)); - } - } - - IEnumerable<IPersistentIdentifierGenerator> pIDg = IterateGenerators(dialect); - foreach (var idGen in pIDg) - { - string[] lines = idGen.SqlDropString(dialect); - if (lines != null) - { - foreach (var line in lines) - { - script.Add(line); - } - } - } - - return script.ToArray(); - } - - public static bool IncludeAction(SchemaAction actionsSource, SchemaAction includedAction) - { - return (actionsSource & includedAction) != SchemaAction.None; - } - - /// <summary> - /// Generate DDL for creating tables - /// </summary> - /// <param name="dialect"></param> - public string[] GenerateSchemaCreationScript(Dialect.Dialect dialect) - { - SecondPassCompile(); - - string defaultCatalog = PropertiesHelper.GetString(Environment.DefaultCatalog, properties, null); - string defaultSchema = PropertiesHelper.GetString(Environment.DefaultSchema, properties, null); - - var script = new List<string>(); - - foreach (var table in TableMappings) - { - if (table.IsPhysicalTable && IncludeAction(table.SchemaActions, SchemaAction.Export)) - { - script.Add(table.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema)); - script.AddRange(table.SqlCommentStrings(dialect, defaultCatalog, defaultSchema)); - } - } - - foreach (var table in TableMappings) - { - if (table.IsPhysicalTable && IncludeAction(table.SchemaActions, SchemaAction.Export)) - { - if (!dialect.SupportsUniqueConstraintInCreateAlterTable) - { - foreach (var uk in table.UniqueKeyIterator) - { - string constraintString = uk.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema); - if (constraintString != null) - { - script.Add(constraintString); - } - } - } - - foreach (var index in table.IndexIterator) - { - script.Add(index.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema)); - } - - if (dialect.HasAlterTable) - { - foreach (var fk in table.ForeignKeyIterator) - { - if (fk.HasPhysicalConstraint && IncludeAction(fk.ReferencedTable.SchemaActions, SchemaAction.Export)) - { - script.Add(fk.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema)); - } - } - } - } - } - - IEnumerable<IPersistentIdentifierGenerator> pIDg = IterateGenerators(dialect); - foreach (var idGen in pIDg) - { - script.AddRange(idGen.SqlCreateStrings(dialect)); - } - - foreach (var auxDbObj in auxiliaryDatabaseObjects) - { - if (auxDbObj.AppliesToDialect(dialect)) - { - script.Add(auxDbObj.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema)); - } - } - - return script.ToArray(); - } - - private void Validate() - { - ValidateEntities(); - - ValidateCollections(); - - ValidateFilterDefs(); - } - - private void ValidateFilterDefs() - { - var filterNames = new HashedSet<string>(); - foreach (var filterDefinition in FilterDefinitions) - { - if(filterDefinition.Value == null) - { - // a class/collection has a filter but the filter-def was not added. - filterNames.Add(filterDefinition.Key); - } - } - if(filterNames.Count > 0) - { - var message = new StringBuilder(); - message.Append("filter-def for filter named "); - foreach (var filterName in filterNames) - { - message.AppendLine(filterName); - } - message.AppendLine("was not found."); - throw new MappingException(message.ToString()); - } - - // check filter-def without reference - if (FilterDefinitions.Count > 0) - { - filterNames.Clear(); - foreach (var persistentClass in ClassMappings) - { - filterNames.AddAll(persistentClass.FilterMap.Keys); - } - foreach (var collectionMapping in CollectionMappings) - { - filterNames.AddAll(collectionMapping.FilterMap.Keys); - filterNames.AddAll(collectionMapping.ManyToManyFilterMap.Keys); - } - foreach (var filterName in FilterDefinitions.Keys) - { - if (!filterNames.Contains(filterName)) - { - // if you are going to remove this exception at least add a log.Error - // because the usage of filter-def, outside its scope, may cause unexpected behaviour - // during queries. - throw new MappingException("filter-def for filter named '" + filterName - + "' was never used to filter classes nor collections."); - } - } - } - } - - private void ValidateCollections() - { - foreach (var col in collections.Values) - { - col.Validate(mapping); - } - } - - private void ValidateEntities() - { - bool validateProxy = PropertiesHelper.GetBoolean(Environment.UseProxyValidator, properties, true); - HashedSet<string> allProxyErrors = null; - IProxyValidator pvalidator = Environment.BytecodeProvider.ProxyFactoryFactory.ProxyValidator; - - foreach (var clazz in classes.Values) - { - clazz.Validate(mapping); - - if (validateProxy) - { - ICollection<string> errors = ValidateProxyInterface(clazz, pvalidator); - if (errors != null) - { - if (allProxyErrors == null) - { - allProxyErrors = new HashedSet<string>(errors); - } - else - { - allProxyErrors.AddAll(errors); - } - } - } - } - - if (allProxyErrors != null) - { - throw new InvalidProxyTypeException(allProxyErrors); - } - } - - private static ICollection<string> ValidateProxyInterface(PersistentClass persistentClass, IProxyValidator validator) - { - if (!persistentClass.IsLazy) - { - // Nothing to validate - return null; - } - - if (persistentClass.ProxyInterface == null) - { - // Nothing to validate - return null; - } - - return validator.ValidateType(persistentClass.ProxyInterface); - } - - /// <summary> - /// Call this to ensure the mappings are fully compiled/built. Usefull to ensure getting - /// access to all information in the metamodel when calling e.g. getClassMappings(). - /// </summary> - public virtual void BuildMappings() - { - SecondPassCompile(); - } - - /// <remarks> - /// This method may be called many times!! - /// </remarks> - private void SecondPassCompile() - { - log.Info("checking mappings queue"); - - mappingsQueue.CheckNoUnavailableEntries(); - - log.Info("processing one-to-many association mappings"); - - foreach (var command in secondPasses) - { - command(classes); - } - - secondPasses.Clear(); - - log.Info("processing one-to-one association property references"); - - foreach (var upr in propertyReferences) - { - PersistentClass clazz = GetClassMapping(upr.referencedClass); - if (clazz == null) - { - throw new MappingException("property-ref to unmapped class: " + upr.referencedClass); - } - - Property prop = clazz.GetReferencedProperty(upr.propertyName); - ((SimpleValue) prop.Value).IsAlternateUniqueKey = true; - } - - //TODO: Somehow add the newly created foreign keys to the internal collection - - log.Info("processing foreign key constraints"); - - ISet done = new HashedSet(); - foreach (var table in TableMappings) - { - SecondPassCompileForeignKeys(table, done); - } - - log.Info("processing filters (second pass)"); - foreach (var filterSecondPassArgs in filtersSecondPasses) - { - FilterDefinition filterDef; - var filterName = filterSecondPassArgs.FilterName; - FilterDefinitions.TryGetValue(filterName, out filterDef); - if(filterDef == null) - { - throw new MappingException("filter-def for filter named " + filterName + " was not found."); - } - if(string.IsNullOrEmpty(filterDef.DefaultFilterCondition)) - { - throw new MappingException("no filter condition found for filter: " + filterName); - } - filterSecondPassArgs.Filterable.FilterMap[filterName] = filterDef.DefaultFilterCondition; - } - } - - private void SecondPassCompileForeignKeys(Table table, ISet done) - { - table.CreateForeignKeys(); - - foreach (var fk in table.ForeignKeyIterator) - { - if (!done.Contains(fk)) - { - done.Add(fk); - - string referencedEntityName = fk.ReferencedEntityName; - if (string.IsNullOrEmpty(referencedEntityName)) - { - throw new MappingException( - string.Format("An association from the table {0} does not specify the referenced entity", fk.Table.Name)); - } - - if (log.IsDebugEnabled) - { - log.Debug("resolving reference to class: " + referencedEntityName); - } - - PersistentClass referencedClass; - if (!classes.TryGetValue(referencedEntityName, out referencedClass)) - { - string message = string.Format("An association from the table {0} refers to an unmapped class: {1}", fk.Table.Name, - referencedEntityName); - - LogAndThrow(new MappingException(message)); - } - else - { - if (referencedClass.IsJoinedSubclass) - { - SecondPassCompileForeignKeys(referencedClass.Superclass.Table, done); - } - - try - { - fk.ReferencedTable = referencedClass.Table; - fk.AlignColumns(); - } - catch (MappingException me) - { - LogAndThrow(me); - } - } - } - } - } - - /// <summary> - /// The named queries - /// </summary> - public IDictionary<string, NamedQueryDefinition> NamedQueries { get; protected set; } - - private EventListeners GetInitializedEventListeners() - { - EventListeners result = eventListeners.ShallowCopy(); - result.InitializeListeners(this); - return result; - } - - /// <summary> - /// Retrieve the user-supplied delegate to handle non-existent entity scenarios. - /// </summary> - /// <remarks> - /// Specify a user-supplied delegate to be used to handle scenarios where an entity could not be - /// located by specified id. This is mainly intended for EJB3 implementations to be able to - /// control how proxy initialization errors should be handled... - /// </remarks> - public IEntityNotFoundDelegate EntityNotFoundDelegate { get; set; } - - public EventListeners EventListeners - { - get { return eventListeners; } - } - - private static readonly IInterceptor emptyInterceptor = new EmptyInterceptor(); - private string defaultAssembly; - private string defaultNamespace; - - protected virtual void ConfigureProxyFactoryFactory() - { - #region Way for the user to specify their own ProxyFactory - - //http://jira.nhibernate.org/browse/NH-975 - - var ipff = Environment.BytecodeProvider as IInjectableProxyFactoryFactory; - string pffClassName; - properties.TryGetValue(Environment.ProxyFactoryFactoryClass, out pffClassName); - if (ipff != null && !string.IsNullOrEmpty(pffClassName)) - { - ipff.SetProxyFactoryFactory(pffClassName); - } - - #endregion - } - /// <summary> - /// Instantiate a new <see cref="ISessionFactory" />, using the properties and mappings in this - /// configuration. The <see cref="ISessionFactory" /> will be immutable, so changes made to the - /// configuration after building the <see cref="ISessionFactory" /> will not affect it. - /// </summary> - /// <returns>An <see cref="ISessionFactory" /> instance.</returns> - public ISessionFactory BuildSessionFactory() - { - - ConfigureProxyFactoryFactory(); - SecondPassCompile(); - Validate(); - Environment.VerifyProperties(properties); - Settings settings = BuildSettings(); - - // Ok, don't need schemas anymore, so free them - Schemas = null; - - return new SessionFactoryImpl(this, mapping, settings, GetInitializedEventListeners()); - } - - /// <summary> - /// Gets or sets the <see cref="IInterceptor"/> to use. - /// </summary> - /// <value>The <see cref="IInterceptor"/> to use.</value> - public IInterceptor Interceptor - { - get { return interceptor; } - set { interceptor = value; } - } - - /// <summary> - /// Gets or sets the <see cref="IDictionary"/> that contains the configuration - /// properties and their values. - /// </summary> - /// <value> - /// The <see cref="IDictionary"/> that contains the configuration - /// properties and their values. - /// </value> - public IDictionary<string, string> Properties - { - get { return properties; } - set { properties = value; } - } - - /// <summary> - /// Set the default assembly to use for the mappings added to the configuration - /// afterwards. - /// </summary> - /// <param name="newDefaultAssembly">The default assembly name.</param> - /// <returns>This configuration instance.</returns> - /// <remarks> - /// This setting can be overridden for a mapping file by setting <c>default-assembly</c> - /// attribute of <c><hibernate-mapping></c> element. - /// </remarks> - public Configuration SetDefaultAssembly(string newDefaultAssembly) - { - defaultAssembly = newDefaultAssembly; - return this; - } - - /// <summary> - /// Set the default namespace to use for the mappings added to the configuration - /// afterwards. - /// </summary> - /// <param name="newDefaultNamespace">The default namespace.</param> - /// <returns>This configuration instance.</returns> - /// <remarks> - /// This setting can be overridden for a mapping file by setting <c>default-namespace</c> - /// attribute of <c><hibernate-mapping></c> element. - /// </remarks> - public Configuration SetDefaultNamespace(string newDefaultNamespace) - { - defaultNamespace = newDefaultNamespace; - return this; - } - - /// <summary> - /// Sets the default interceptor for use by all sessions. - /// </summary> - /// <param name="newInterceptor">The default interceptor.</param> - /// <returns>This configuration instance.</returns> - public Configuration SetInterceptor(IInterceptor newInterceptor) - { - interceptor = newInterceptor; - return this; - } - - /// <summary> - /// Specify a completely new set of properties - /// </summary> - public Configuration SetProperties(IDictionary<string, string> newProperties) - { - properties = newProperties; - return this; - } - - /// <summary> - /// Adds an <see cref="IDictionary"/> of configuration properties. The - /// Key is the name of the Property and the Value is the <see cref="String"/> - /// value of the Property. - /// </summary> - /// <param name="additionalProperties">An <see cref="IDictionary"/> of configuration properties.</param> - /// <returns> - /// This <see cref="Configuration"/> object. - /// </returns> - public Configuration AddProperties(IDictionary<string, string> additionalProperties) - { - foreach (var de in additionalProperties) - { - properties.Add(de.Key, de.Value); - } - return this; - } - - /// <summary> - /// Sets the value of the configuration property. - /// </summary> - /// <param name="name">The name of the property.</param> - /// <param name="value">The value of the property.</param> - /// <returns> - /// This configuration object. - /// </returns> - public Configuration SetProperty(string name, string value) - { - properties[name] = value; - return this; - } - - /// <summary> - /// Gets the value of the configuration property. - /// </summary> - /// <param name="name">The name of the property.</param> - /// <returns>The configured value of the property, or <see langword="null" /> if the property was not specified.</returns> - public string GetProperty(string name) - { - return PropertiesHelper.GetString(name, properties, null); - } - - private void AddProperties(ISessionFactoryConfiguration factoryConfiguration) - { - foreach (var kvp in factoryConfiguration.Properties) - { - if (log.IsDebugEnabled) - { - log.Debug(kvp.Key + "=" + kvp.Value); - } - properties[kvp.Key] = kvp.Value; - } - Environment.VerifyProperties(properties); - } - - // TODO - getConfigurationInputStream(String resource) - - /// <summary> - /// Configure NHibernate using the <c><hibernate-configuration></c> section - /// from the application config file, if found, or the file <c>hibernate.cfg.xml</c> if the - /// <c><hibernate-configuration></c> section not include the session-factory configuration. - /// </summary> - /// <returns>A configuration object initialized with the file.</returns> - /// <remarks> - /// To configure NHibernate explicitly using <c>hibernate.cfg.xml</c>, appling merge/override - /// of the application configuration file, use this code: - /// <code> - /// configuration.Configure("path/to/hibernate.cfg.xml"); - /// </code> - /// </remarks> - public Configuration Configure() - { - var hc = ConfigurationManager.GetSection(CfgXmlHelper.CfgSectionName) as IHibernateConfiguration; - if (hc != null && hc.SessionFactory != null) - { - return DoConfigure(hc.SessionFactory); - } - else - { - return Configure(GetDefaultConfigurationFilePath()); - } - } - - /// <summary> - /// Configure NHibernate using the file specified. - /// </summary> - /// <param name="fileName">The location of the XML file to use to configure NHibernate.</param> - /// <returns>A Configuration object initialized with the file.</returns> - /// <remarks> - /// Calling Configure(string) will override/merge the values set in app.config or web.config - /// </remarks> - public Configuration Configure(string fileName) - { - return Configure(fileName, false); - } - - private Configuration Configure(string fileName, bool ignoreSessionFactoryConfig) - { - if (ignoreSessionFactoryConfig) - { - Environment.ResetSessionFactoryProperties(); - properties = Environment.Properties; - } - - XmlTextReader reader = null; - try - { - reader = new XmlTextReader(fileName); - return Configure(reader); - } - finally - { - if (reader != null) - { - reader.Close(); - } - } - } - - /// <summary> - /// Configure NHibernate using a resource contained in an Assembly. - /// </summary> - /// <param name="assembly">The <see cref="Assembly"/> that contains the resource.</param> - /// <param name="resourceName">The name of the manifest resource being requested.</param> - /// <returns>A Configuration object initialized from the manifest resource.</returns> - /// <remarks> - /// Calling Configure(Assembly, string) will overwrite the values set in app.config or web.config - /// </remarks> - public Configuration Configure(Assembly assembly, string resourceName) - { - if (assembly == null) - { - throw new HibernateException("Could not configure NHibernate.", new ArgumentNullException("assembly")); - } - - if (resourceName == null) - { - throw new HibernateException("Could not configure NHibernate.", new ArgumentNullException("resourceName")); - } - - Stream stream = null; - try - { - stream = assembly.GetManifestResourceStream(resourceName); - if (stream == null) - { - // resource does not exist - throw appropriate exception - throw new HibernateException("A ManifestResourceStream could not be created for the resource " + resourceName - + " in Assembly " + assembly.FullName); - } - - return Configure(new XmlTextReader(stream)); - } - finally - { - if (stream != null) - { - stream.Close(); - } - } - } - - /// <summary> - /// Configure NHibernate using the specified XmlReader. - /// </summary> - /// <param name="textReader">The <see cref="XmlReader"/> that contains the Xml to configure NHibernate.</param> - /// <returns>A Configuration object initialized with the file.</returns> - /// <remarks> - /// Calling Configure(XmlReader) will overwrite the values set in app.config or web.config - /// </remarks> - public Configuration Configure(XmlReader textReader) - { - if (textReader == null) - { - throw new HibernateConfigException("Could not configure NHibernate.", - new ArgumentException("A null value was passed in.", "textReader")); - } - - try - { - IHibernateConfiguration hc = new HibernateConfiguration(textReader); - return DoConfigure(hc.SessionFactory); - } - catch (Exception e) - { - log.Error("Problem parsing configuration", e); - throw; - } - } - - // Not ported - configure(org.w3c.dom.Document) - - protected Configuration DoConfigure(ISessionFactoryConfiguration factoryConfiguration) - { - if (!string.IsNullOrEmpty(factoryConfiguration.Name)) - { - properties[Environment.SessionFactoryName] = factoryConfiguration.Name; - } - - AddProperties(factoryConfiguration); - - // Load mappings - foreach (var mc in factoryConfiguration.Mappings) - { - if (mc.IsEmpty()) - { - throw new HibernateConfigException("<mapping> element in configuration specifies no attributes"); - } - if (!string.IsNullOrEmpty(mc.Resource) && !string.IsNullOrEmpty(mc.Assembly)) - { - log.Debug(factoryConfiguration.Name + "<-" + mc.Resource + " in " + mc.Assembly); - AddResource(mc.Resource, Assembly.Load(mc.Assembly)); - } - else if (!string.IsNullOrEmpty(mc.Assembly)) - { - log.Debug(factoryConfiguration.Name + "<-" + mc.Assembly); - AddAssembly(mc.Assembly); - } - else if (!string.IsNullOrEmpty(mc.File)) - { - log.Debug(factoryConfiguration.Name + "<-" + mc.File); - AddFile(mc.File); - } - } - - // Load class-cache - foreach (var ccc in factoryConfiguration.ClassesCache) - { - string region = string.IsNullOrEmpty(ccc.Region) ? ccc.Class : ccc.Region; - bool includeLazy = (ccc.Include != ClassCacheInclude.NonLazy); - SetCacheConcurrencyStrategy(ccc.Class, EntityCacheUsageParser.ToString(ccc.Usage), region, includeLazy); - } - - // Load collection-cache - foreach (var ccc in factoryConfiguration.CollectionsCache) - { - string role = ccc.Collection; - NHibernate.Mapping.Collection collection = GetCollectionMapping(role); - if (collection == null) - { - throw new HibernateConfigException( - "collection-cache Configuration: Cannot configure cache for unknown collection role " + role); - } - - string region = string.IsNullOrEmpty(ccc.Region) ? role : ccc.Region; - SetCollectionCacheConcurrencyStrategy(role, EntityCacheUsageParser.ToString(ccc.Usage), region); - } - - // Events - foreach (var ec in factoryConfiguration.Events) - { - var listenerClasses = new string[ec.Listeners.Count]; - for (int i = 0; i < ec.Listeners.Count; i++) - { - listenerClasses[i] = ec.Listeners[i].Class; - } - log.Debug("Event listeners: " + ec.Type + "=" + StringHelper.ToString(listenerClasses)); - SetListeners(ec.Type, listenerClasses); - } - // Listeners - foreach (var lc in factoryConfiguration.Listeners) - { - log.Debug("Event listener: " + lc.Type + "=" + lc.Class); - SetListeners(lc.Type, new[] {lc.Class}); - } - - if (!string.IsNullOrEmpty(factoryConfiguration.Name)) - { - log.Info("Configured SessionFactory: " + factoryConfiguration.Name); - } - log.Debug("properties: " + properties); - - return this; - } - - internal RootClass GetRootClassMapping(string clazz) - { - try - { - return (RootClass) GetClassMapping(clazz); - } - catch (InvalidCastException) - { - throw new HibernateConfigException( - "class-cache Configuration: You may only specify a cache for root <class> mappings " + "(cache was specified for " - + clazz + ")"); - } - } - - internal RootClass GetRootClassMapping(System.Type clazz) - { - PersistentClass persistentClass = GetClassMapping(clazz); - - if (persistentClass == null) - { - throw new HibernateConfigException("class-cache Configuration: Cache specified for unmapped class " + clazz); - } - - var rootClass = persistentClass as RootClass; - - if (rootClass == null) - { - throw new HibernateConfigException( - "class-cache Configuration: You may only specify a cache for root <class> mappings " + "(cache was specified for " - + clazz + ")"); - } - - return rootClass; - } - - /// <summary> - /// Set up a cache for an entity class - /// </summary> - public Configuration SetCacheConcurrencyStrategy(String clazz, String concurrencyStrategy) - { - SetCacheConcurrencyStrategy(clazz, concurrencyStrategy, clazz); - return this; - } - - public void SetCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region) - { - SetCacheConcurrencyStrategy(clazz, concurrencyStrategy, region, true); - } - - internal void SetCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region, bool includeLazy) - { - RootClass rootClass = GetRootClassMapping(StringHelper.GetFullClassname(clazz)); - if (rootClass == null) - { - throw new HibernateConfigException("Cannot cache an unknown entity: " + clazz); - } - rootClass.CacheConcurrencyStrategy = concurrencyStrategy; - rootClass.CacheRegionName = region; - rootClass.SetLazyPropertiesCacheable(includeLazy); - } - - /// <summary> - /// Set up a cache for a collection role - /// </summary> - public Configuration SetCollectionCacheConcurrencyStrategy(string collectionRole, string concurrencyStrategy) - { - SetCollectionCacheConcurrencyStrategy(collectionRole, concurrencyStrategy, collectionRole); - return this; - } - - internal void SetCollectionCacheConcurrencyStrategy(string collectionRole, string concurrencyStrategy, string region) - { - NHibernate.Mapping.Collection collection = GetCollectionMapping(collectionRole); - collection.CacheConcurrencyStrategy = concurrencyStrategy; - collection.CacheRegionName = region; - } - - /// <summary> - /// Get the query language imports (entityName/className -> AssemblyQualifiedName) - /// </summary> - public IDictionary<string, string> Imports { get; protected set; } - - /// <summary> - /// Create an object-oriented view of the configuration properties - /// </summary> - /// <returns>A <see cref="Settings"/> object initialized from the settings properties.</returns> - //protected Settings BuildSettings() - private Settings BuildSettings() - { - var result = settingsFactory.BuildSettings(properties); - // NH : Set configuration for IdGenerator SQL logging - PersistentIdGeneratorParmsNames.SqlStatementLogger.FormatSql = result.SqlStatementLogger.FormatSql; - PersistentIdGeneratorParmsNames.SqlStatementLogger.LogToStdout = result.SqlStatementLogger.LogToStdout; - return result; - } - - /// <summary> - /// The named SQL queries - /// </summary> - public IDictionary<string, NamedSQLQueryDefinition> NamedSQLQueries - { - get; protected set; - } - - /// <summary> - /// Naming strategy for tables and columns - /// </summary> - public INamingStrategy NamingStrategy - { - get { return namingStrategy; } - } - - /// <summary> - /// Set a custom naming strategy - /// </summary> - /// <param name="newNamingStrategy">the NamingStrategy to set</param> - /// <returns></returns> - public Configuration SetNamingStrategy(INamingStrategy newNamingStrategy) - { - namingStrategy = newNamingStrategy; - return this; - } - - public IDictionary<string, ResultSetMappingDefinition> SqlResultSetMappings - { - get; - protected set; - } - - public IDictionary<string, FilterDefinition> FilterDefinitions { get; protected set; } - - public void AddFilterDefinition(FilterDefinition definition) - { - FilterDefinitions.Add(definition.FilterName, definition); - } - - public void AddAuxiliaryDatabaseObject(IAuxiliaryDatabaseObject obj) - { - auxiliaryDatabaseObjects.Add(obj); - } - - public IDictionary<string, ISQLFunction> SqlFunctions { get; protected set; } - - public void AddSqlFunction(string functionName, ISQLFunction sqlFunction) - { - SqlFunctions[functionName] = sqlFunction; - } - - #region NHibernate-Specific Members - - /// <summary> - /// Load and validate the mappings in the <see cref="XmlReader" /> against - /// the nhibernate-mapping-2.2 schema, without adding them to the configuration. - /// </summary> - /// <remarks> - /// This method is made public to be usable from the unit tests. It is not intended - /// to be called by end users. - /// </remarks> - /// <param name="hbmReader">The XmlReader that contains the mapping.</param> - /// <param name="name">The name of the document, for error reporting purposes.</param> - /// <returns>NamedXmlDocument containing the validated XmlDocument built from the XmlReader.</returns> - public NamedXmlDocument LoadMappingDocument(XmlReader hbmReader, string name) - { - XmlReaderSettings settings = Schemas.CreateMappingReaderSettings(); -... [truncated message content] |
From: <ric...@us...> - 2010-01-19 12:53:27
|
Revision: 4921 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4921&view=rev Author: ricbrown Date: 2010-01-19 12:53:21 +0000 (Tue, 19 Jan 2010) Log Message: ----------- Improvement to projection list syntax in QueryOver. (Thanks to maciejk for suggesting improvement in NH-Forge blog reply) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs trunk/nhibernate/src/NHibernate/IQueryOver.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs 2010-01-19 10:31:20 UTC (rev 4920) +++ trunk/nhibernate/src/NHibernate/Criterion/Lambda/QueryOverProjectionBuilder.cs 2010-01-19 12:53:21 UTC (rev 4921) @@ -9,18 +9,14 @@ namespace NHibernate.Criterion.Lambda { - public class QueryOverProjectionBuilder<TReturn, TRoot, TSubType> + public class QueryOverProjectionBuilder<T> { - private TReturn fluentReturn; - private IQueryOver<TRoot,TSubType> criteria; private ProjectionList projectionList; private IProjection lastProjection = null; - public QueryOverProjectionBuilder(TReturn fluentReturn, IQueryOver<TRoot,TSubType> criteria) + public QueryOverProjectionBuilder() { - this.fluentReturn = fluentReturn; - this.criteria = criteria; projectionList = Projections.ProjectionList(); } @@ -36,23 +32,19 @@ lastProjection = projection; } - /// <summary> - /// Create the ProjectionList and return to the query - /// </summary> - public TReturn EndSelect + internal ProjectionList ProjectionList { get { AddLastProjection(); - criteria.Select(projectionList); - return fluentReturn; + return projectionList; } } /// <summary> /// Create an alias for the previous projection /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> WithAlias(Expression<Func<object>> alias) + public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias) { string aliasContainer = ExpressionProcessor.FindMemberExpression(alias.Body); lastProjection = Projections.Alias(lastProjection, aliasContainer); @@ -62,7 +54,7 @@ /// <summary> /// Select an arbitrary projection /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> Select(IProjection projection) + public QueryOverProjectionBuilder<T> Select(IProjection projection) { PushProjection(projection); return this; @@ -71,7 +63,7 @@ /// <summary> /// A property average value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectAvg(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectAvg(Expression<Func<T, object>> expression) { PushProjection(Projections.Avg(expression)); return this; @@ -80,7 +72,7 @@ /// <summary> /// A property average value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectAvg(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectAvg(Expression<Func<object>> expression) { PushProjection(Projections.Avg(expression)); return this; @@ -89,7 +81,7 @@ /// <summary> /// A property value count /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectCount(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectCount(Expression<Func<T, object>> expression) { PushProjection(Projections.Count(expression)); return this; @@ -98,7 +90,7 @@ /// <summary> /// A property value count /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectCount(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectCount(Expression<Func<object>> expression) { PushProjection(Projections.Count(expression)); return this; @@ -107,7 +99,7 @@ /// <summary> /// A distinct property value count /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectCountDistinct(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectCountDistinct(Expression<Func<T, object>> expression) { PushProjection(Projections.CountDistinct(expression)); return this; @@ -116,7 +108,7 @@ /// <summary> /// A distinct property value count /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectCountDistinct(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectCountDistinct(Expression<Func<object>> expression) { PushProjection(Projections.CountDistinct(expression)); return this; @@ -125,7 +117,7 @@ /// <summary> /// A grouping property value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectGroup(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectGroup(Expression<Func<T, object>> expression) { PushProjection(Projections.Group(expression)); return this; @@ -134,7 +126,7 @@ /// <summary> /// A grouping property value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectGroup(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectGroup(Expression<Func<object>> expression) { PushProjection(Projections.Group(expression)); return this; @@ -143,7 +135,7 @@ /// <summary> /// A property maximum value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectMax(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectMax(Expression<Func<T, object>> expression) { PushProjection(Projections.Max(expression)); return this; @@ -152,7 +144,7 @@ /// <summary> /// A property maximum value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectMax(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectMax(Expression<Func<object>> expression) { PushProjection(Projections.Max(expression)); return this; @@ -161,7 +153,7 @@ /// <summary> /// A property minimum value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectMin(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectMin(Expression<Func<T, object>> expression) { PushProjection(Projections.Min(expression)); return this; @@ -170,7 +162,7 @@ /// <summary> /// A property minimum value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectMin(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectMin(Expression<Func<object>> expression) { PushProjection(Projections.Min(expression)); return this; @@ -179,7 +171,7 @@ /// <summary> /// A projected property value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> Select(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> Select(Expression<Func<T, object>> expression) { PushProjection(Projections.Property(expression)); return this; @@ -188,13 +180,13 @@ /// <summary> /// A projected property value /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> Select(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> Select(Expression<Func<object>> expression) { PushProjection(Projections.Property(expression)); return this; } - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectSubQuery<U>(QueryOver<U> detachedQueryOver) + public QueryOverProjectionBuilder<T> SelectSubQuery<U>(QueryOver<U> detachedQueryOver) { PushProjection(Projections.SubQuery(detachedQueryOver)); return this; @@ -203,7 +195,7 @@ /// <summary> /// A property value sum /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectSum(Expression<Func<TSubType, object>> expression) + public QueryOverProjectionBuilder<T> SelectSum(Expression<Func<T, object>> expression) { PushProjection(Projections.Sum(expression)); return this; @@ -212,7 +204,7 @@ /// <summary> /// A property value sum /// </summary> - public QueryOverProjectionBuilder<TReturn, TRoot, TSubType> SelectSum(Expression<Func<object>> expression) + public QueryOverProjectionBuilder<T> SelectSum(Expression<Func<object>> expression) { PushProjection(Projections.Sum(expression)); return this; Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2010-01-19 10:31:20 UTC (rev 4920) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2010-01-19 12:53:21 UTC (rev 4921) @@ -264,9 +264,10 @@ return this; } - public QueryOverProjectionBuilder<QueryOver<TRoot,TSubType>, TRoot, TSubType> SelectList + public QueryOver<TRoot, TSubType> Select(Func<QueryOverProjectionBuilder<TSubType>, QueryOverProjectionBuilder<TSubType>> list) { - get { return new QueryOverProjectionBuilder<QueryOver<TRoot,TSubType>, TRoot, TSubType>(this, this); } + criteria.SetProjection(list(new QueryOverProjectionBuilder<TSubType>()).ProjectionList); + return this; } public QueryOverOrderBuilder<TRoot,TSubType> OrderBy(Expression<Func<TSubType, object>> path) @@ -604,8 +605,8 @@ IQueryOver<TRoot,TSubType> IQueryOver<TRoot,TSubType>.Select(params IProjection[] projections) { return Select(projections); } - QueryOverProjectionBuilder<IQueryOver<TRoot,TSubType>, TRoot, TSubType> IQueryOver<TRoot,TSubType>.SelectList - { get { return new QueryOverProjectionBuilder<IQueryOver<TRoot,TSubType>,TRoot,TSubType>(this, this); } } + IQueryOver<TRoot, TSubType> IQueryOver<TRoot, TSubType>.Select(Func<QueryOverProjectionBuilder<TSubType>, QueryOverProjectionBuilder<TSubType>> list) + { return Select(list); } IQueryOverOrderBuilder<TRoot,TSubType> IQueryOver<TRoot,TSubType>.OrderBy(Expression<Func<TSubType, object>> path) { return new IQueryOverOrderBuilder<TRoot,TSubType>(this, path); } Modified: trunk/nhibernate/src/NHibernate/IQueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryOver.cs 2010-01-19 10:31:20 UTC (rev 4920) +++ trunk/nhibernate/src/NHibernate/IQueryOver.cs 2010-01-19 12:53:21 UTC (rev 4921) @@ -208,9 +208,9 @@ IQueryOver<TRoot,TSubType> Select(params IProjection[] projections); /// <summary> - /// Create a list of projections inline + /// Create a list of projections using a projection builder /// </summary> - QueryOverProjectionBuilder<IQueryOver<TRoot,TSubType>, TRoot, TSubType> SelectList { get; } + IQueryOver<TRoot, TSubType> Select(Func<QueryOverProjectionBuilder<TSubType>, QueryOverProjectionBuilder<TSubType>> list); /// <summary> /// Add order expressed as a lambda expression Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2010-01-19 10:31:20 UTC (rev 4920) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2010-01-19 12:53:21 UTC (rev 4921) @@ -231,9 +231,7 @@ QueryOver<Child> averageChildAge = QueryOver.Of<Child>() - .SelectList - .SelectAvg(c => c.Age) - .EndSelect; + .Select(p => p.SelectAvg(c => c.Age)); QueryOver<Child> childCountQuery = QueryOver.Of<Child>() @@ -243,11 +241,10 @@ var nameAndChildCount = s.QueryOver<Person>(() => personAlias) .WithSubquery.Where(p => p.Age <= averageChildAge.As<int>()) - .SelectList + .Select(list => list .Select(p => p.Name) - .SelectSubQuery(childCountQuery).WithAlias(() => childCountAlias) - .EndSelect - .OrderBy(() => childCountAlias).Desc + .SelectSubQuery(childCountQuery).WithAlias(() => childCountAlias)) + .OrderBy(() => childCountAlias).Desc .List<object[]>() .Select(props => new { Name = (string)props[0], Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2010-01-19 10:31:20 UTC (rev 4920) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/ProjectionsFixture.cs 2010-01-19 12:53:21 UTC (rev 4921) @@ -114,7 +114,7 @@ Person personAgeProjectionAlias = null; var actual = CreateTestQueryOver<Person>(() => personAlias) - .SelectList + .Select(list => list .SelectAvg(p => p.Age).WithAlias(() => personAgeProjectionAlias) .Select(Projections.Avg("Age")) // allows private properties .SelectAvg(() => personAlias.Age) @@ -132,8 +132,7 @@ .Select(() => personAlias.Age) .SelectSubQuery(DetachedQueryOverAge) .SelectSum(p => p.Age) - .SelectSum(() => personAlias.Age) - .EndSelect; + .SelectSum(() => personAlias.Age)); AssertCriteriaAreEqual(expected, actual); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ste...@us...> - 2010-01-19 10:31:27
|
Revision: 4920 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4920&view=rev Author: steverstrong Date: 2010-01-19 10:31:20 +0000 (Tue, 19 Jan 2010) Log Message: ----------- Upgraded to latest re-linq version Modified Paths: -------------- trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ClientSideTransformOperator.cs trunk/nhibernate/src/NHibernate/Linq/ResultTransformer.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Linq/MethodCallTests.cs Removed Paths: ------------- trunk/nhibernate/lib/net/3.5/Remotion.Interfaces.dll trunk/nhibernate/lib/net/3.5/Remotion.dll Modified: trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll =================================================================== (Binary files differ) Deleted: trunk/nhibernate/lib/net/3.5/Remotion.Interfaces.dll =================================================================== (Binary files differ) Deleted: trunk/nhibernate/lib/net/3.5/Remotion.dll =================================================================== (Binary files differ) Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -261,7 +261,7 @@ return new HqlBitwiseNot(_factory); } - public HqlBooleanNot Not(HqlBooleanExpression operand) + public HqlBooleanNot BooleanNot(HqlBooleanExpression operand) { return new HqlBooleanNot(_factory, operand); } Modified: trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -75,7 +75,7 @@ // All has two arguments. Arg 1 is the source and arg 2 is the predicate var predicate = (LambdaExpression)arguments[1]; - return treeBuilder.Not( + return treeBuilder.BooleanNot( treeBuilder.Exists( treeBuilder.Query( treeBuilder.SelectFrom( @@ -86,7 +86,7 @@ ) ), treeBuilder.Where( - treeBuilder.Not(visitor.Visit(arguments[1]).AsBooleanExpression()) + treeBuilder.BooleanNot(visitor.Visit(arguments[1]).AsBooleanExpression()) ) ) ) Modified: trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -3,6 +3,7 @@ using System.Linq; using System.Linq.Expressions; using NHibernate.Engine.Query; +using NHibernate.Hql.Ast; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Linq.ResultOperators; using NHibernate.Linq.Visitors; @@ -71,7 +72,7 @@ ExpressionToHqlTranslationResults = QueryModelVisitor.GenerateHqlQuery(queryModel, _constantToParameterMap, - requiredHqlParameters); + requiredHqlParameters, true); ParameterDescriptors = requiredHqlParameters.AsReadOnly(); _astNode = ExpressionToHqlTranslationResults.Statement.AstNode; Modified: trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ClientSideTransformOperator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ClientSideTransformOperator.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ClientSideTransformOperator.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -1,4 +1,5 @@ using System; +using System.Linq.Expressions; using Remotion.Data.Linq.Clauses; using Remotion.Data.Linq.Clauses.StreamedData; @@ -20,5 +21,9 @@ { throw new NotImplementedException(); } + + public override void TransformExpressions(Func<Expression, Expression> transformation) + { + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/ResultTransformer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ResultTransformer.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/ResultTransformer.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -3,7 +3,6 @@ using System.Linq; using System.Linq.Expressions; using NHibernate.Transform; -using Remotion.Collections; namespace NHibernate.Linq { Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -325,7 +325,7 @@ switch (expression.NodeType) { case ExpressionType.Not: - return _hqlTreeBuilder.Not(VisitExpression(expression.Operand).AsBooleanExpression()); + return _hqlTreeBuilder.BooleanNot(VisitExpression(expression.Operand).AsBooleanExpression()); case ExpressionType.Convert: return VisitExpression(expression.Operand); } @@ -415,7 +415,7 @@ protected HqlTreeNode VisitSubQueryExpression(SubQueryExpression expression) { - ExpressionToHqlTranslationResults query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, _requiredHqlParameters); + ExpressionToHqlTranslationResults query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, _requiredHqlParameters, false); return query.Statement; } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -21,7 +21,7 @@ { public class QueryModelVisitor : QueryModelVisitorBase { - public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel queryModel, IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) + public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel queryModel, IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters, bool root) { // Remove unnecessary body operators RemoveUnnecessaryBodyOperators.ReWrite(queryModel); @@ -44,7 +44,7 @@ // Flatten pointless subqueries QueryReferenceExpressionFlattener.ReWrite(queryModel); - var visitor = new QueryModelVisitor(parameters, requiredHqlParameters); + var visitor = new QueryModelVisitor(parameters, requiredHqlParameters, root); visitor.VisitQueryModel(queryModel); return visitor.GetTranslation(); @@ -62,20 +62,28 @@ private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; private readonly IList<NamedParameterDescriptor> _requiredHqlParameters; + private readonly bool _root; private bool _serverSide = true; private HqlTreeNode _treeNode; + private System.Type _resultType; - private QueryModelVisitor(IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) + private QueryModelVisitor(IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters, bool root) { _parameters = parameters; _requiredHqlParameters = requiredHqlParameters; - _hqlTreeBuilder = new HqlTreeBuilder(); + _root = root; + _hqlTreeBuilder = new HqlTreeBuilder(); _treeNode = _hqlTreeBuilder.Query(_hqlTreeBuilder.SelectFrom(_hqlTreeBuilder.From())); } public ExpressionToHqlTranslationResults GetTranslation() { + if (_root) + { + DetectOuterExists(); + } + return new ExpressionToHqlTranslationResults(_treeNode, _itemTransformers, _listTransformers, @@ -83,6 +91,20 @@ _additionalCriteria); } + private void DetectOuterExists() + { + if (_treeNode is HqlExists) + { + _treeNode = _treeNode.Children.First(); + + _additionalCriteria.Add((q, p) => q.SetMaxResults(1)); + + Expression<Func<IEnumerable<object>, bool>> x = l => l.Any(); + + _listTransformers.Add(x); + } + } + public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel) { AddFromClause(_hqlTreeBuilder.Range( @@ -194,6 +216,14 @@ { ProcessAggregateOperator((AggregateResultOperator)resultOperator); } + else if (resultOperator is AnyResultOperator) + { + ProcessAnyOperator((AnyResultOperator) resultOperator); + } + else if (resultOperator is AllResultOperator) + { + ProcessAllOperator((AllResultOperator) resultOperator); + } else { throw new NotSupportedException(string.Format("The {0} result operator is not current supported", @@ -201,6 +231,20 @@ } } + private void ProcessAllOperator(AllResultOperator resultOperator) + { + AddWhereClause(_hqlTreeBuilder.BooleanNot( + HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.Predicate, _parameters, + _requiredHqlParameters).AsBooleanExpression())); + + _treeNode = _hqlTreeBuilder.BooleanNot(_hqlTreeBuilder.Exists((HqlQuery)_treeNode)); + } + + private void ProcessAnyOperator(AnyResultOperator anyOperator) + { + _treeNode = _hqlTreeBuilder.Exists((HqlQuery) _treeNode); + } + private void ProcessContainsOperator(ContainsResultOperator resultOperator) { var itemExpression = Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-19 10:31:20 UTC (rev 4920) @@ -55,10 +55,6 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\..\lib\net\3.5\log4net.dll</HintPath> </Reference> - <Reference Include="Remotion, Version=1.13.9.2, Culture=neutral, PublicKeyToken=cab60358ab4081ea, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\lib\net\3.5\Remotion.dll</HintPath> - </Reference> <Reference Include="Remotion.Data.Linq, Version=1.13.9.2, Culture=neutral, PublicKeyToken=cab60358ab4081ea, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\..\lib\net\3.5\Remotion.Data.Linq.dll</HintPath> Modified: trunk/nhibernate/src/NHibernate.Test/Linq/MethodCallTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/MethodCallTests.cs 2010-01-17 19:31:11 UTC (rev 4919) +++ trunk/nhibernate/src/NHibernate.Test/Linq/MethodCallTests.cs 2010-01-19 10:31:20 UTC (rev 4920) @@ -7,7 +7,6 @@ public class MethodCallTests : LinqTestCase { [Test] - [Ignore("Waiting for re-linq support")] public void CanExecuteAny() { bool result = db.Users.Any(); @@ -15,7 +14,6 @@ } [Test] - [Ignore("Waiting for re-linq support")] public void CanExecuteAnyWithArguments() { bool result = db.Users.Any(u => u.Name == "user-does-not-exist"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-01-17 19:31:17
|
Revision: 4919 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4919&view=rev Author: ricbrown Date: 2010-01-17 19:31:11 +0000 (Sun, 17 Jan 2010) Log Message: ----------- Fix NH-2009 (Many-to-one fails when using property-ref against a joined property) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs trunk/nhibernate/src/NHibernate/Loader/Entity/EntityJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate/Mapping/ForeignKey.cs trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Model.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -1137,7 +1137,7 @@ try { - fk.ReferencedTable = referencedClass.Table; + fk.AddReferencedTable(referencedClass); fk.AlignColumns(); } catch (MappingException me) Modified: trunk/nhibernate/src/NHibernate/Loader/Entity/EntityJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Entity/EntityJoinWalker.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Loader/Entity/EntityJoinWalker.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -29,6 +29,14 @@ } /// <summary> + /// Override to use the persister to change the table-alias for columns in join-tables + /// </summary> + protected override string GenerateAliasForColumn(string rootAlias, string column) + { + return Persister.GenerateTableAliasForColumn(rootAlias, column); + } + + /// <summary> /// Disable outer join fetching if this loader obtains an /// upgrade lock mode /// </summary> Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -667,6 +667,11 @@ return buf.ToSqlString(); } + protected virtual string GenerateAliasForColumn(string rootAlias, string column) + { + return rootAlias; + } + /// <summary> /// Render the where condition for a (batch) load by identifier / collection key /// </summary> @@ -676,7 +681,8 @@ { // if not a composite key, use "foo in (?, ?, ?)" for batching // if no batch, and not a composite key, use "foo = ?" - InFragment inf = new InFragment().SetColumn(alias, columnNames[0]); + string tableAlias = GenerateAliasForColumn(alias, columnNames[0]); + InFragment inf = new InFragment().SetColumn(tableAlias, columnNames[0]); for (int i = 0; i < batchSize; i++) inf.AddValue(Parameter.Placeholder); Modified: trunk/nhibernate/src/NHibernate/Mapping/ForeignKey.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ForeignKey.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Mapping/ForeignKey.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -158,6 +158,18 @@ referencedColumns.Add(column); } + internal void AddReferencedTable(PersistentClass referencedClass) + { + if (referencedColumns.Count > 0) + { + referencedTable = referencedColumns[0].Value.Table; + } + else + { + referencedTable = referencedClass.Table; + } + } + public override string ToString() { if (!IsReferenceToPrimaryKey) Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -1817,6 +1817,16 @@ } } + public string GenerateTableAliasForColumn(string rootAlias, string column) + { + int propertyIndex = Array.IndexOf(SubclassColumnClosure, column); + + if (propertyIndex < 0) + return rootAlias; + + return GenerateTableAlias(rootAlias, SubclassColumnTableNumberClosure[propertyIndex]); + } + public string GenerateTableAlias(string rootAlias, int tableNumber) { if (tableNumber == 0) Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -113,5 +113,10 @@ /// Return the alised identifier column names /// </summary> string[] ToIdentifierColumns(string alias); + + /// <summary> + /// Get the table alias used for the supplied column + /// </summary> + string GenerateTableAliasForColumn(string rootAlias, string column); } } \ No newline at end of file Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Fixture.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -0,0 +1,50 @@ +using System; +using System.Collections; +using NHibernate.Criterion; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2009 +{ + [TestFixture] + public class Fixture : BugTestCase + { + [Test] + public void PropertyRefToJoinedTable() + { + BlogPost savedBlogPost = new BlogPost(); + + using (ISession session = OpenSession()) + { + User user1 = new User(); + user1.FullName = "First User"; + user1.UserName = "User1"; + session.Save(user1); + + User user2 = new User(); + user2.FullName = "Second User"; + user2.UserName = "User2"; + session.Save(user2); + + savedBlogPost.Title = "Post 1"; + savedBlogPost.Poster = user1; + session.Save(savedBlogPost); + + session.Flush(); + session.Clear(); + } + + using (ISession session = OpenSession()) + { + var user = session.Get<BlogPost>(savedBlogPost.ID); + } + + using (ISession session = OpenSession()) + using (ITransaction tx = session.BeginTransaction()) + { + session.Delete("from User"); + session.Delete("from BlogPost"); + tx.Commit(); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Mappings.hbm.xml 2010-01-17 19:31:11 UTC (rev 4919) @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2009" + assembly="NHibernate.Test"> + + <class name="BlogPost" table="blogpost_table"> + <id name="ID" column="blogpost_id"> + <generator class="native"/> + </id> + <property name="Title" column="blogpost_title"/> + <many-to-one name="Poster" column="poster_id" property-ref="UserName" /> + </class> + + <class name="User" table="user_table"> + <id name="ID" column="user_id"> + <generator class="native"/> + </id> + <property name="FullName" column="user_fullname" unique="true"/> + <join table="ADUser"> + <key column="user_id"/> + <property name="UserName" column="aduser_username" unique="true"/> + </join> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2009/Model.cs 2010-01-17 19:31:11 UTC (rev 4919) @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NHibernate.Test.NHSpecificTest.NH2009 +{ + public class BlogPost + { + public virtual int ID { get; set; } + public virtual string Title { get; set; } + public virtual User Poster { get; set; } + } + + public class User + { + public virtual int ID { get; set; } + public virtual string FullName { get; set; } + public virtual string UserName { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-13 16:03:54 UTC (rev 4918) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-17 19:31:11 UTC (rev 4919) @@ -663,6 +663,8 @@ <Compile Include="NHSpecificTest\NH1978\_401k.cs" /> <Compile Include="NHSpecificTest\NH1989\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1989\Model.cs" /> + <Compile Include="NHSpecificTest\NH2009\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2009\Model.cs" /> <Compile Include="NHSpecificTest\NH2044\DomainClass.cs" /> <Compile Include="NHSpecificTest\NH2044\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH2055\AuxType.cs" /> @@ -2108,6 +2110,7 @@ <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> <EmbeddedResource Include="NHSpecificTest\NH2065\Mappings.hbm.xml" /> + <EmbeddedResource Include="NHSpecificTest\NH2009\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1989\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1978\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2044\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-13 16:04:02
|
Revision: 4918 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4918&view=rev Author: ayenderahien Date: 2010-01-13 16:03:54 +0000 (Wed, 13 Jan 2010) Log Message: ----------- Adding passing test Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/HQL/Ast/HqlFixture.cs Modified: trunk/nhibernate/src/NHibernate.Test/HQL/Ast/HqlFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/HQL/Ast/HqlFixture.cs 2010-01-13 15:56:35 UTC (rev 4917) +++ trunk/nhibernate/src/NHibernate.Test/HQL/Ast/HqlFixture.cs 2010-01-13 16:03:54 UTC (rev 4918) @@ -63,6 +63,16 @@ Check(plan.ReturnMetadata, true, false); } + [Test] + public void OrderByPropertiesImplicitlySpecifiedInTheSelect() + { + // NH-2035 + using (ISession s = OpenSession()) + { + s.CreateQuery("select distinct z from Animal a join a.zoo as z order by z.name").List(); + } + } + [Test] public void CaseClauseInSelect() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-13 15:56:50
|
Revision: 4917 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4917&view=rev Author: ayenderahien Date: 2010-01-13 15:56:35 +0000 (Wed, 13 Jan 2010) Log Message: ----------- Fixing NH-2065 - better error message on reassociation of dirty collection Fixing NH-2064 - changed exception for filters definition without usage to lor.Error Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs trunk/nhibernate/src/NHibernate/Event/Default/OnLockVisitor.cs trunk/nhibernate/src/NHibernate.Test/FilterTest/ConfigFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Model.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2010-01-10 19:01:42 UTC (rev 4916) +++ trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2010-01-13 15:56:35 UTC (rev 4917) @@ -965,8 +965,7 @@ // if you are going to remove this exception at least add a log.Error // because the usage of filter-def, outside its scope, may cause unexpected behaviour // during queries. - throw new MappingException("filter-def for filter named '" + filterName - + "' was never used to filter classes nor collections."); + log.ErrorFormat("filter-def for filter named '{0}' was never used to filter classes nor collections.\r\nThis may result in unexpected behavior during queries", filterName); } } } Modified: trunk/nhibernate/src/NHibernate/Event/Default/OnLockVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/OnLockVisitor.cs 2010-01-10 19:01:42 UTC (rev 4916) +++ trunk/nhibernate/src/NHibernate/Event/Default/OnLockVisitor.cs 2010-01-13 15:56:35 UTC (rev 4917) @@ -36,14 +36,14 @@ // a "detached" collection that originally belonged to the same entity if (persistentCollection.IsDirty) { - throw new HibernateException("reassociated object has dirty collection"); + throw new HibernateException("reassociated object has dirty collection: " + persistentCollection.Role); } ReattachCollection(persistentCollection, type); } else { // a "detached" collection that belonged to a different entity - throw new HibernateException("reassociated object has dirty collection reference"); + throw new HibernateException("reassociated object has dirty collection reference: " + persistentCollection.Role); } } else @@ -51,7 +51,7 @@ // a collection loaded in the current session // can not possibly be the collection belonging // to the entity passed to update() - throw new HibernateException("reassociated object has dirty collection reference"); + throw new HibernateException("reassociated object has dirty collection reference: " + persistentCollection.Role); } } else Modified: trunk/nhibernate/src/NHibernate.Test/FilterTest/ConfigFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/FilterTest/ConfigFixture.cs 2010-01-10 19:01:42 UTC (rev 4916) +++ trunk/nhibernate/src/NHibernate.Test/FilterTest/ConfigFixture.cs 2010-01-13 15:56:35 UTC (rev 4917) @@ -1,6 +1,11 @@ +using System; using System.Collections.Generic; +using log4net; +using log4net.Appender; +using log4net.Config; using NHibernate.Cfg; using NUnit.Framework; +using System.Linq; namespace NHibernate.Test.FilterTest { @@ -236,9 +241,20 @@ var cfg = GetConfiguration(); cfg.AddXmlString(filterDef); - var e = Assert.Throws<MappingException>(() => cfg.BuildSessionFactory()); - Assert.That(e.Message, Text.StartsWith("filter-def for filter named")); - Assert.That(e.Message, Text.Contains("was never used to filter classes nor collections.")); + var memoryAppender = new MemoryAppender(); + BasicConfigurator.Configure(memoryAppender); + try + { + cfg.BuildSessionFactory(); + + var wholeLog = String.Join("\r\n", memoryAppender.GetEvents().Select(x => x.RenderedMessage).ToArray()); + Assert.That(wholeLog, Text.Contains("filter-def for filter named")); + Assert.That(wholeLog, Text.Contains("was never used to filter classes nor collections.")); + } + finally + { + LogManager.Shutdown(); + } } } } Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Fixture.cs 2010-01-13 15:56:35 UTC (rev 4917) @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Transactions; +using NHibernate.Impl; +using NUnit.Framework; +using NHibernate.Criterion; + +namespace NHibernate.Test.NHSpecificTest.NH2065 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void OnSetUp() + { + using (var s = OpenSession()) + using (s.BeginTransaction()) + { + var person = new Person + { + Children = new HashSet<Person>() + }; + s.Save(person); + var child = new Person(); + s.Save(child); + person.Children.Add(child); + + s.Transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var s = OpenSession()) + using (s.BeginTransaction()) + { + s.Delete("from Person"); + s.Transaction.Commit(); + } + } + + [Test] + [ExpectedException( + ExpectedException=typeof(HibernateException), + ExpectedMessage="reassociated object has dirty collection: NHibernate.Test.NHSpecificTest.NH2065.Person.Children")] + public void GetGoodErrorForDirtyReassociatedCollection() + { + Person person; + using (var s = OpenSession()) + using (s.BeginTransaction()) + { + person = s.Get<Person>(1); + NHibernateUtil.Initialize(person.Children); + s.Transaction.Commit(); + } + + person.Children.Clear(); + + using (var s = OpenSession()) + using (s.BeginTransaction()) + { + s.Lock(person, LockMode.None); + } + } + + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Mappings.hbm.xml 2010-01-13 15:56:35 UTC (rev 4917) @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2065"> + + <class name="Person"> + <id name="Id"> + <generator class="increment" /> + </id> + <property name="Name"/> + + <set name="Children"> + <key column="ParentId"/> + <one-to-many class="Person"/> + </set> + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2065/Model.cs 2010-01-13 15:56:35 UTC (rev 4917) @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2065 +{ + public class Person + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual ICollection<Person> Children { get; set; } + } + +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-10 19:01:42 UTC (rev 4916) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-13 15:56:35 UTC (rev 4917) @@ -692,6 +692,8 @@ <Compile Include="NHSpecificTest\NH2011\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2011\Model.cs" /> <Compile Include="NHSpecificTest\NH2030\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2065\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2065\Model.cs" /> <Compile Include="NHSpecificTest\NH473\Child.cs" /> <Compile Include="NHSpecificTest\NH473\Fixture.cs" /> <Compile Include="NHSpecificTest\NH473\Parent.cs" /> @@ -2105,6 +2107,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2065\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1989\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1978\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2044\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-01-10 19:01:49
|
Revision: 4916 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4916&view=rev Author: ricbrown Date: 2010-01-10 19:01:42 +0000 (Sun, 10 Jan 2010) Log Message: ----------- Fix NH-1989 (Future queries not using second level cache) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs trunk/nhibernate/src/NHibernate/Impl/DelayedEnumerator.cs trunk/nhibernate/src/NHibernate/Impl/FutureBatch.cs trunk/nhibernate/src/NHibernate/Impl/FutureCriteriaBatch.cs trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs trunk/nhibernate/src/NHibernate/Impl/FutureValue.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Model.cs Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -56,6 +56,16 @@ this.parameterMetadata = parameterMetadata; } + public bool Cacheable + { + get { return cacheable; } + } + + public string CacheRegion + { + get { return cacheRegion; } + } + public bool HasNamedParameters { get { return parameterMetadata.NamedParameterNames.Count > 0; } Modified: trunk/nhibernate/src/NHibernate/Impl/DelayedEnumerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/DelayedEnumerator.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/DelayedEnumerator.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -5,7 +5,7 @@ { internal class DelayedEnumerator<T> : IEnumerable<T> { - public delegate IList<T> GetResult(); + public delegate IEnumerable<T> GetResult(); private readonly GetResult result; Modified: trunk/nhibernate/src/NHibernate/Impl/FutureBatch.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/FutureBatch.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/FutureBatch.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Generic; +using System.Linq; namespace NHibernate.Impl { @@ -9,6 +10,8 @@ private readonly IList<System.Type> resultTypes = new List<System.Type>(); private int index; private IList results; + private bool isCacheable = true; + private string cacheRegion; protected readonly SessionImpl session; @@ -31,9 +34,16 @@ public void Add<TResult>(TQueryApproach query) { + if (queries.Count == 0) + { + cacheRegion = CacheRegion(query); + } + queries.Add(query); resultTypes.Add(typeof(TResult)); index = queries.Count - 1; + isCacheable = isCacheable && IsQueryCacheable(query); + isCacheable = isCacheable && (cacheRegion == CacheRegion(query)); } public void Add(TQueryApproach query) @@ -55,7 +65,7 @@ private void GetResults() { - var multiApproach = CreateMultiApproach(); + var multiApproach = CreateMultiApproach(isCacheable, cacheRegion); for (int i = 0; i < queries.Count; i++) { AddTo(multiApproach, queries[i], resultTypes[i]); @@ -64,14 +74,16 @@ ClearCurrentFutureBatch(); } - private IList<TResult> GetCurrentResult<TResult>(int currentIndex) + private IEnumerable<TResult> GetCurrentResult<TResult>(int currentIndex) { - return (IList<TResult>)Results[currentIndex]; + return ((IList)Results[currentIndex]).Cast<TResult>(); } - protected abstract TMultiApproach CreateMultiApproach(); + protected abstract TMultiApproach CreateMultiApproach(bool isCacheable, string cacheRegion); protected abstract void AddTo(TMultiApproach multiApproach, TQueryApproach query, System.Type resultType); protected abstract IList GetResultsFrom(TMultiApproach multiApproach); protected abstract void ClearCurrentFutureBatch(); + protected abstract bool IsQueryCacheable(TQueryApproach query); + protected abstract string CacheRegion(TQueryApproach query); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Impl/FutureCriteriaBatch.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/FutureCriteriaBatch.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/FutureCriteriaBatch.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -6,9 +6,12 @@ { public FutureCriteriaBatch(SessionImpl session) : base(session) {} - protected override IMultiCriteria CreateMultiApproach() + protected override IMultiCriteria CreateMultiApproach(bool isCacheable, string cacheRegion) { - return session.CreateMultiCriteria(); + return + session.CreateMultiCriteria() + .SetCacheable(isCacheable) + .SetCacheRegion(cacheRegion); } protected override void AddTo(IMultiCriteria multiApproach, ICriteria query, System.Type resultType) @@ -25,5 +28,15 @@ { session.FutureCriteriaBatch = null; } + + protected override bool IsQueryCacheable(ICriteria query) + { + return ((CriteriaImpl)query).Cacheable; + } + + protected override string CacheRegion(ICriteria query) + { + return ((CriteriaImpl)query).CacheRegion; + } } } Modified: trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -6,9 +6,12 @@ { public FutureQueryBatch(SessionImpl session) : base(session) {} - protected override IMultiQuery CreateMultiApproach() + protected override IMultiQuery CreateMultiApproach(bool isCacheable, string cacheRegion) { - return session.CreateMultiQuery(); + return + session.CreateMultiQuery() + .SetCacheable(isCacheable) + .SetCacheRegion(cacheRegion); } protected override void AddTo(IMultiQuery multiApproach, IQuery query, System.Type resultType) @@ -25,5 +28,15 @@ { session.FutureQueryBatch = null; } + + protected override bool IsQueryCacheable(IQuery query) + { + return ((AbstractQueryImpl)query).Cacheable; + } + + protected override string CacheRegion(IQuery query) + { + return ((AbstractQueryImpl)query).CacheRegion; + } } } Modified: trunk/nhibernate/src/NHibernate/Impl/FutureValue.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/FutureValue.cs 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate/Impl/FutureValue.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -5,7 +5,7 @@ { internal class FutureValue<T> : IFutureValue<T> { - public delegate IList<T> GetResult(); + public delegate IEnumerable<T> GetResult(); private readonly GetResult getResult; @@ -19,13 +19,14 @@ get { var result = getResult(); + var enumerator = result.GetEnumerator(); - if (result.Count == 0) - { + if (!enumerator.MoveNext()) + { return default(T); } - return result[0]; + return enumerator.Current; } } } Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Fixture.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -0,0 +1,274 @@ +using System.Data; + +using NUnit.Framework; + +using NHibernate.Cache; +using NHibernate.Cfg; +using NHibernate.Criterion; +using NHibernate.Engine; + +using System.Collections.Generic; +using System.Linq; + +namespace NHibernate.Test.NHSpecificTest.NH1989 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void OnSetUp() + { + cfg.Properties[Environment.CacheProvider] = typeof(HashtableCacheProvider).AssemblyQualifiedName; + cfg.Properties[Environment.UseQueryCache] = "true"; + sessions = (ISessionFactoryImplementor)cfg.BuildSessionFactory(); + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete("from User"); + tx.Commit(); + } + } + + private static void DeleteObjectsOutsideCache(ISession s) + { + using (IDbCommand cmd = s.Connection.CreateCommand()) + { + cmd.CommandText = "DELETE FROM UserTable"; + cmd.ExecuteNonQuery(); + } + } + + [Test] + public void SecondLevelCacheWithSingleCacheableFuture() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + User user = new User() { Name="test" }; + s.Save(user); + tx.Commit(); + } + + using (ISession s = OpenSession()) + { + // Query results should be cached + User user = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Not.Null); + + DeleteObjectsOutsideCache(s); + } + + using (ISession s = OpenSession()) + { + User user = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Not.Null, + "entity not retrieved from cache"); + } + } + + [Test] + public void SecondLevelCacheWithDifferentRegionsFuture() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + User user = new User() { Name="test" }; + s.Save(user); + tx.Commit(); + } + + using (ISession s = OpenSession()) + { + // Query results should be cached + User user = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .SetCacheRegion("region1") + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Not.Null); + + DeleteObjectsOutsideCache(s); + } + + using (ISession s = OpenSession()) + { + User user = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .SetCacheRegion("region2") + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Null, + "entity from different region should not be retrieved"); + } + } + + [Test] + public void SecondLevelCacheWithMixedCacheableAndNonCacheableFuture() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + User user = new User() { Name="test" }; + s.Save(user); + tx.Commit(); + } + + using (ISession s = OpenSession()) + { + // cacheable Future, not evaluated yet + IFutureValue<User> userFuture = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .FutureValue<User>(); + + // non cacheable Future causes batch to be non-cacheable + int count = + s.CreateCriteria<User>() + .SetProjection(Projections.RowCount()) + .FutureValue<int>() + .Value; + + Assert.That(userFuture.Value, Is.Not.Null); + Assert.That(count, Is.EqualTo(1)); + + DeleteObjectsOutsideCache(s); + } + + using (ISession s = OpenSession()) + { + IFutureValue<User> userFuture = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .FutureValue<User>(); + + int count = + s.CreateCriteria<User>() + .SetProjection(Projections.RowCount()) + .FutureValue<int>() + .Value; + + Assert.That(userFuture.Value, Is.Null, + "query results should not come from cache"); + } + } + + [Test] + public void SecondLevelCacheWithMixedCacheRegionsFuture() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + User user = new User() { Name="test" }; + s.Save(user); + tx.Commit(); + } + + using (ISession s = OpenSession()) + { + // cacheable Future, not evaluated yet + IFutureValue<User> userFuture = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .SetCacheRegion("region1") + .FutureValue<User>(); + + // different cache-region causes batch to be non-cacheable + int count = + s.CreateCriteria<User>() + .SetProjection(Projections.RowCount()) + .SetCacheable(true) + .SetCacheRegion("region2") + .FutureValue<int>() + .Value; + + Assert.That(userFuture.Value, Is.Not.Null); + Assert.That(count, Is.EqualTo(1)); + + DeleteObjectsOutsideCache(s); + } + + using (ISession s = OpenSession()) + { + IFutureValue<User> userFuture = + s.CreateCriteria<User>() + .Add(Restrictions.NaturalId().Set("Name", "test")) + .SetCacheable(true) + .SetCacheRegion("region1") + .FutureValue<User>(); + + int count = + s.CreateCriteria<User>() + .SetProjection(Projections.RowCount()) + .SetCacheable(true) + .SetCacheRegion("region2") + .FutureValue<int>() + .Value; + + Assert.That(userFuture.Value, Is.Null, + "query results should not come from cache"); + } + } + + [Test] + public void SecondLevelCacheWithSingleCacheableQueryFuture() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + User user = new User() { Name="test" }; + s.Save(user); + tx.Commit(); + } + + using (ISession s = OpenSession()) + { + // Query results should be cached + User user = + s.CreateQuery("from User u where u.Name='test'") + .SetCacheable(true) + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Not.Null); + + DeleteObjectsOutsideCache(s); + } + + using (ISession s = OpenSession()) + { + User user = + s.CreateQuery("from User u where u.Name='test'") + .SetCacheable(true) + .FutureValue<User>() + .Value; + + Assert.That(user, Is.Not.Null, + "entity not retrieved from cache"); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Mappings.hbm.xml 2010-01-10 19:01:42 UTC (rev 4916) @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH1989" + assembly="NHibernate.Test"> + + <class name="User" table="UserTable"> + <cache usage="read-write"/> + <id name="Id"> + <generator class="guid.comb"/> + </id> + <natural-id> + <property name="Name" /> + </natural-id> + </class> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1989/Model.cs 2010-01-10 19:01:42 UTC (rev 4916) @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH1989 +{ + public class User + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-08 10:09:47 UTC (rev 4915) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-10 19:01:42 UTC (rev 4916) @@ -661,6 +661,8 @@ <Compile Include="NHSpecificTest\NH1978\AliasTest.cs" /> <Compile Include="NHSpecificTest\NH1978\Employee.cs" /> <Compile Include="NHSpecificTest\NH1978\_401k.cs" /> + <Compile Include="NHSpecificTest\NH1989\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH1989\Model.cs" /> <Compile Include="NHSpecificTest\NH2044\DomainClass.cs" /> <Compile Include="NHSpecificTest\NH2044\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH2055\AuxType.cs" /> @@ -2103,6 +2105,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH1989\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1978\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2044\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2030\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-08 10:09:54
|
Revision: 4915 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4915&view=rev Author: ayenderahien Date: 2010-01-08 10:09:47 +0000 (Fri, 08 Jan 2010) Log Message: ----------- Explicitly set parameter sizes - prevent query cache plan per each actual parameter size Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Driver/OdbcDriver.cs trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs Modified: trunk/nhibernate/src/NHibernate/Driver/OdbcDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/OdbcDriver.cs 2010-01-08 06:57:28 UTC (rev 4914) +++ trunk/nhibernate/src/NHibernate/Driver/OdbcDriver.cs 2010-01-08 10:09:47 UTC (rev 4915) @@ -69,7 +69,7 @@ public override IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes) { IDbCommand command = base.GenerateCommand(type, sqlString, parameterTypes); - if (IsPrepareSqlEnabled) + //if (IsPrepareSqlEnabled) { SetParameterSizes(command.Parameters, parameterTypes); } Modified: trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs 2010-01-08 06:57:28 UTC (rev 4914) +++ trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs 2010-01-08 10:09:47 UTC (rev 4915) @@ -153,7 +153,7 @@ public override IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes) { IDbCommand command = base.GenerateCommand(type, sqlString, parameterTypes); - if (IsPrepareSqlEnabled) + //if (IsPrepareSqlEnabled) { SetParameterSizes(command.Parameters, parameterTypes); } Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs 2010-01-08 06:57:28 UTC (rev 4914) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs 2010-01-08 10:09:47 UTC (rev 4915) @@ -14,7 +14,7 @@ protected override string GetExpectedInsertOrgLogStatement(string orgName) { - return string.Format("exec nh_organization_native_id_insert @p0;@p0 = '{0}' [Type: String ({1})]", orgName, orgName.Length); + return string.Format("exec nh_organization_native_id_insert @p0;@p0 = '{0}' [Type: String (4000)]", orgName); } protected override IList Mappings This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-08 06:57:38
|
Revision: 4914 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4914&view=rev Author: ayenderahien Date: 2010-01-08 06:57:28 +0000 (Fri, 08 Jan 2010) Log Message: ----------- Adding parameter type information for SQL log, that allow to detect issues with parameter types and length Modified Paths: -------------- trunk/nhibernate/src/NHibernate/AdoNet/Util/SqlStatementLogger.cs trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs Property Changed: ---------------- trunk/nhibernate/ Property changes on: trunk/nhibernate ___________________________________________________________________ Modified: svn:mergeinfo - /branches/2.1.x/nhibernate:4690-4691,4696-4697,4711,4715-4716 + /branches/2.1.x/nhibernate:4690-4691,4696-4697,4711,4715-4716,4905-4908 Modified: trunk/nhibernate/src/NHibernate/AdoNet/Util/SqlStatementLogger.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/Util/SqlStatementLogger.cs 2010-01-06 22:32:59 UTC (rev 4913) +++ trunk/nhibernate/src/NHibernate/AdoNet/Util/SqlStatementLogger.cs 2010-01-08 06:57:28 UTC (rev 4914) @@ -93,14 +93,23 @@ } appendComma = true; p = (IDataParameter)command.Parameters[i]; - output.Append(string.Format("{0} = {1}", p.ParameterName, GetParameterLogableValue(p))); + output.Append(string.Format("{0} = {1} [Type: {2}]", p.ParameterName, GetParameterLogableValue(p), GetParameterLogableType(p))); } outputText = output.ToString(); } return outputText; } - public string GetParameterLogableValue(IDataParameter parameter) + private static string GetParameterLogableType(IDataParameter dataParameter) + { + var p = dataParameter as IDbDataParameter; + if (p != null) + return p.DbType + " (" + p.Size + ")"; + return p.DbType.ToString(); + + } + + public string GetParameterLogableValue(IDataParameter parameter) { if (parameter.Value == null || DBNull.Value.Equals(parameter.Value)) { Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs 2010-01-06 22:32:59 UTC (rev 4913) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Identity/MsSQL/MSSQLIdentityInsertWithStoredProcsTest.cs 2010-01-08 06:57:28 UTC (rev 4914) @@ -14,7 +14,7 @@ protected override string GetExpectedInsertOrgLogStatement(string orgName) { - return string.Format("exec nh_organization_native_id_insert @p0;@p0 = '{0}'", orgName); + return string.Format("exec nh_organization_native_id_insert @p0;@p0 = '{0}' [Type: String ({1})]", orgName, orgName.Length); } protected override IList Mappings This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aye...@us...> - 2010-01-06 22:33:08
|
Revision: 4913 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4913&view=rev Author: ayenderahien Date: 2010-01-06 22:32:59 +0000 (Wed, 06 Jan 2010) Log Message: ----------- NH1978 - NH will now generate proper aliases for legacy tables that starts with numbers NH-1248 - Subqueries.IsNull Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Util/StringHelper.cs trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Criterion/NullSubqueryExpression.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/AliasTest.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Employee.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/_401k.cs Added: trunk/nhibernate/src/NHibernate/Criterion/NullSubqueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/NullSubqueryExpression.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Criterion/NullSubqueryExpression.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -0,0 +1,19 @@ +using System; +using NHibernate.SqlCommand; + +namespace NHibernate.Criterion +{ + [Serializable] + public class NullSubqueryExpression : SubqueryExpression + { + protected override SqlString ToLeftSqlString(ICriteria criteria, ICriteriaQuery outerQuery) + { + return SqlString.Empty; + } + + internal NullSubqueryExpression(String quantifier, DetachedCriteria dc) + : base(null, quantifier, dc, false) + { + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -318,5 +318,14 @@ return Subqueries.NotExists(detachedQuery.DetachedCriteria); } + public static AbstractCriterion IsNull(DetachedCriteria dc) + { + return new NullSubqueryExpression("IS NULL", dc); + } + + public static AbstractCriterion IsNotNull(DetachedCriteria dc) + { + return new NullSubqueryExpression("IS NOT NULL", dc); + } } } Modified: trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -14,17 +14,25 @@ { private readonly CriteriaImpl criteriaImpl; private readonly String quantifier; - private readonly String op; + private readonly bool prefixOp; + private readonly String op; private QueryParameters parameters; private IType[] types; [NonSerialized] private CriteriaQueryTranslator innerQuery; - protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) + protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) + :this(op, quantifier, dc, true) + { + + } + + protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc, bool prefixOp) { criteriaImpl = dc.GetCriteriaImpl(); this.quantifier = quantifier; - this.op = op; + this.prefixOp = prefixOp; + this.op = op; } public IType[] GetTypes() @@ -68,16 +76,27 @@ buf.Add(" ").Add(op).Add(" "); } - if (quantifier != null) + if (quantifier != null && prefixOp) { buf.Add(quantifier).Add(" "); } - return buf.Add("(").Add(sql).Add(")").ToSqlString(); + + buf.Add("(").Add(sql).Add(")"); + + if(quantifier!=null && prefixOp==false) + { + buf.Add(" ").Add(quantifier); + } + + return buf.ToSqlString(); } public override string ToString() { - return string.Format("{0} {1} ({2})", op, quantifier, criteriaImpl); + if(prefixOp) + return string.Format("{0} {1} ({2})", op, quantifier, criteriaImpl); + return string.Format("{0} ({1}) {2}", op, criteriaImpl, quantifier); + } public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-06 22:32:59 UTC (rev 4913) @@ -579,6 +579,7 @@ <Compile Include="Criterion\Lambda\QueryOverRestrictionBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverSubqueryBuilder.cs" /> <Compile Include="Criterion\Lambda\QueryOverSubqueryPropertyBuilder.cs" /> + <Compile Include="Criterion\NullSubqueryExpression.cs" /> <Compile Include="Criterion\ProjectionsExtensions.cs" /> <Compile Include="Dialect\MsSql2008Dialect.cs" /> <Compile Include="Dialect\InformixDialect0940.cs" /> Modified: trunk/nhibernate/src/NHibernate/Util/StringHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -620,10 +620,11 @@ { return result + "x"; //ick! } - else + if(char.IsLetter(result[0]) || '_' == result[0]) { return result; } + return "alias_" + result; } public static string MoveAndToBeginning(string filter) Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -127,6 +127,33 @@ } } + [Test] + public void TestSubcriteriaBeingNull() + { + ISession session = OpenSession(); + ITransaction t = session.BeginTransaction(); + + Course hibernateCourse = new Course(); + hibernateCourse.CourseCode = "HIB"; + hibernateCourse.Description = "Hibernate Training"; + session.Save(hibernateCourse); + + DetachedCriteria subcriteria = DetachedCriteria.For<Enrolment>("e"); + subcriteria.Add(Expression.EqProperty("e.CourseCode", "c.CourseCode")); + subcriteria.SetProjection(Projections.Avg("Semester")); + + DetachedCriteria criteria = DetachedCriteria.For<Course>("c"); + criteria.SetProjection(Projections.Count("id")); + criteria.Add(Expression.Or(Subqueries.Le(5, subcriteria), Subqueries.IsNull(subcriteria))); + + object o = criteria.GetExecutableCriteria(session).UniqueResult(); + Assert.AreEqual(1, o); + + session.Delete(hibernateCourse); + t.Commit(); + session.Close(); + } + [Test] public void Subselect() { Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/AliasTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/AliasTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/AliasTest.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -0,0 +1,25 @@ +using NHibernate.Cfg; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH1978 +{ + [TestFixture] + public class AliasTest : BugTestCase + { + [Test] + public void ShouldReturnPlanFromEmployee() + { + using(var s = OpenSession()) + using (var trans = s.BeginTransaction()) + { + var plan = new _401k {PlanName = "test"}; + s.Save(plan); + s.Refresh(plan); + var emp = new Employee {EmpName = "name", PlanParent = plan}; + s.Save(emp); + + trans.Rollback(); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Employee.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Employee.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Employee.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -0,0 +1,12 @@ +namespace NHibernate.Test.NHSpecificTest.NH1978 +{ + /// <summary> + /// Category object for NHibernate mapped table 'Categories'. + /// </summary> + public class Employee + { + public virtual int ID { get; set; } + public virtual string EmpName { get; set; } + public virtual _401k PlanParent { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/Mappings.hbm.xml 2010-01-06 22:32:59 UTC (rev 4913) @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping + namespace="NHibernate.Test.NHSpecificTest.NH1978" + assembly="NHibernate.Test" + xmlns="urn:nhibernate-mapping-2.2"> + <class name="Employee" lazy="true" table="Employee"> + <id name="ID" type="Int32" unsaved-value="0"> + <generator class="native" /> + </id> + <property name="EmpName" type="String"> + </property> + <many-to-one name="PlanParent" class="_401k" > + <column name="Plan401kID" sql-type="int" not-null="false" /> + </many-to-one> + </class> + <class name="_401k" lazy="true" table="[401k]"> + <id name="ID" type="Int32" unsaved-value="0"> + <generator class="native" /> + </id> + <property name="PlanName" type="String"> + </property> + <bag name="Employees" inverse="true" lazy="true" cascade="all-delete-orphan" > + <key column="Plan401kID" /> + <one-to-many class="Employee"/> + </bag> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/_401k.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/_401k.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1978/_401k.cs 2010-01-06 22:32:59 UTC (rev 4913) @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH1978 +{ + /// <summary> + /// Product object for NHibernate mapped table 'Products'. + /// </summary> + public class _401k + { + public virtual int ID { get; set; } + public virtual string PlanName { get; set; } + public virtual IList<Employee> Employees { get; set; } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-06 22:11:57 UTC (rev 4912) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2010-01-06 22:32:59 UTC (rev 4913) @@ -658,6 +658,9 @@ <Compile Include="NHSpecificTest\NH1938\Model.cs" /> <Compile Include="NHSpecificTest\NH1939\AuxType.cs" /> <Compile Include="NHSpecificTest\NH1939\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH1978\AliasTest.cs" /> + <Compile Include="NHSpecificTest\NH1978\Employee.cs" /> + <Compile Include="NHSpecificTest\NH1978\_401k.cs" /> <Compile Include="NHSpecificTest\NH2044\DomainClass.cs" /> <Compile Include="NHSpecificTest\NH2044\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH2055\AuxType.cs" /> @@ -2100,6 +2103,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH1978\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2044\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2030\Mappings.hbm.xml" /> <EmbeddedResource Include="Linq\Mappings\Patient.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |