|
From: <dar...@us...> - 2009-01-27 03:49:30
|
Revision: 4003
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4003&view=rev
Author: darioquintana
Date: 2009-01-27 03:49:11 +0000 (Tue, 27 Jan 2009)
Log Message:
-----------
Adding support for IQuery.Future<T>()
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Engine/ISessionImplementor.cs
trunk/nhibernate/src/NHibernate/IQuery.cs
trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs
trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs
trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Engine/ISessionImplementor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/ISessionImplementor.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/Engine/ISessionImplementor.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -285,5 +285,7 @@
int ExecuteUpdate(string query, QueryParameters queryParameters);
FutureCriteriaBatch FutureCriteriaBatch { get; }
+
+ FutureQueryBatch FutureQueryBatch { get; }
}
}
Modified: trunk/nhibernate/src/NHibernate/IQuery.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/IQuery.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/IQuery.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -584,5 +584,22 @@
/// "shape" of the query result.
/// </summary>
IQuery SetResultTransformer(IResultTransformer resultTransformer);
+
+ /// <summary>
+ /// Get a enumerable that when enumerated will execute
+ /// a batch of queries in a single database roundtrip
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ IEnumerable<T> Future<T>();
+
+ /// Get an IFutureValue instance, whose value can be retrieved through
+ /// its Value property. The query is not executed until the Value property
+ /// is retrieved, which will execute other Future queries as well in a
+ /// single roundtrip
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ IFutureValue<T> FutureValue<T>();
}
}
Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/Impl/AbstractQueryImpl.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -826,7 +826,19 @@
return this;
}
- /// <summary> Override the current session cache mode, just for this query.
+ public IEnumerable<T> Future<T>()
+ {
+ session.FutureQueryBatch.Add(this);
+ return session.FutureQueryBatch.GetEnumerator<T>();
+ }
+
+ public IFutureValue<T> FutureValue<T>()
+ {
+ session.FutureQueryBatch.Add(this);
+ return session.FutureQueryBatch.GetFutureValue<T>();
+ }
+
+ /// <summary> Override the current session cache mode, just for this query.
/// </summary>
/// <param name="cacheMode">The cache mode to use. </param>
/// <returns> this (for method chaining) </returns>
Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -129,6 +129,7 @@
public abstract int ExecuteNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters);
public abstract int ExecuteUpdate(string query, QueryParameters queryParameters);
public abstract FutureCriteriaBatch FutureCriteriaBatch { get; internal set; }
+ public abstract FutureQueryBatch FutureQueryBatch { get; internal set; }
public virtual IQuery GetNamedQuery(string queryName)
{
Added: trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Impl/FutureQueryBatch.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -0,0 +1,126 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace NHibernate.Impl
+{
+ public class FutureQueryBatch
+ {
+ private readonly List<IQuery> queries = new List<IQuery>();
+ private int index;
+ private IList results;
+ private readonly ISession session;
+
+ public FutureQueryBatch(ISession session)
+ {
+ this.session = session;
+ }
+
+ public IList Results
+ {
+ get
+ {
+ if (results == null)
+ {
+ var multiQuery = session.CreateMultiQuery();
+ foreach (var crit in queries)
+ {
+ multiQuery.Add(crit);
+ }
+ results = multiQuery.List();
+ ((SessionImpl)session).FutureQueryBatch = null;
+ }
+ return results;
+ }
+ }
+
+ public void Add(IQuery query)
+ {
+ queries.Add(query);
+ index = queries.Count - 1;
+ }
+
+ public IFutureValue<T> GetFutureValue<T>()
+ {
+ int currentIndex = index;
+ return new FutureValue<T>(() => (IList)Results[currentIndex]);
+ }
+
+ public IEnumerable<T> GetEnumerator<T>()
+ {
+ int currentIndex = index;
+ return new DelayedEnumerator<T>(() => (IList)Results[currentIndex]);
+ }
+
+ #region Nested type: FutureValue
+
+ private class FutureValue<T> : IFutureValue<T>
+ {
+ public delegate IList GetResult();
+
+ private readonly GetResult getResult;
+
+ public FutureValue(GetResult result)
+ {
+ getResult = result;
+ }
+
+ public T Value
+ {
+ get
+ {
+ var result = getResult();
+
+ if (result.Count == 0)
+ {
+ return default(T);
+ }
+
+ return (T)result[0];
+ }
+ }
+ }
+
+ #endregion
+
+ #region Nested type: DelayedEnumerator
+
+ private class DelayedEnumerator<T> : IEnumerable<T>
+ {
+ public delegate IList GetResult();
+
+ private readonly GetResult result;
+
+ public DelayedEnumerator(GetResult result)
+ {
+ this.result = result;
+ }
+
+ public IEnumerable<T> Enumerable
+ {
+ get
+ {
+ foreach (T item in result())
+ {
+ yield return item;
+ }
+ }
+ }
+
+ #region IEnumerable<T> Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)Enumerable).GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return Enumerable.GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ #endregion
+ }
+}
Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -50,6 +50,7 @@
[NonSerialized] private readonly EntityMode entityMode = EntityMode.Poco;
[NonSerialized] private FutureCriteriaBatch futureCriteriaBatch;
+ [NonSerialized] private FutureQueryBatch futureQueryBatch;
[NonSerialized]
private readonly EventListeners listeners;
@@ -264,6 +265,20 @@
}
}
+ public override FutureQueryBatch FutureQueryBatch
+ {
+ get
+ {
+ if (futureQueryBatch == null)
+ futureQueryBatch = new FutureQueryBatch(this);
+ return futureQueryBatch;
+ }
+ internal set
+ {
+ futureQueryBatch = value;
+ }
+ }
+
/// <summary></summary>
public override IBatcher Batcher
{
Modified: trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/Impl/StatelessSessionImpl.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -819,6 +819,12 @@
internal set { throw new System.NotSupportedException("future queries are not supported for stateless session"); }
}
+ public override FutureQueryBatch FutureQueryBatch
+ {
+ get { throw new System.NotSupportedException("future queries are not supported for stateless session"); }
+ internal set { throw new System.NotSupportedException("future queries are not supported for stateless session"); }
+ }
+
public override IEntityPersister GetEntityPersister(string entityName, object obj)
{
CheckAndUpdateSessionStatus();
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-01-27 03:49:11 UTC (rev 4003)
@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
+ <ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5909BFE7-93CF-4E5F-BE22-6293368AF01D}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -458,6 +458,7 @@
<Compile Include="Exceptions\TemplatedViolatedConstraintNameExtracter.cs" />
<Compile Include="Id\SelectGenerator.cs" />
<Compile Include="IFutureValue.cs" />
+ <Compile Include="Impl\FutureQueryBatch.cs" />
<Compile Include="Impl\FutureCriteriaBatch.cs" />
<Compile Include="Properties\BackFieldStrategy.cs" />
<Compile Include="Bytecode\CodeDom\BytecodeProviderImpl.cs" />
Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Futures/FutureQueryFixture.cs 2009-01-27 03:49:11 UTC (rev 4003)
@@ -0,0 +1,122 @@
+using NHibernate.Criterion;
+using NHibernate.Impl;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.Futures
+{
+ using System.Collections;
+
+ [TestFixture]
+ public class FutureQueryFixture : TestCase
+ {
+
+ protected override IList Mappings
+ {
+ get { return new string[] { "NHSpecificTest.Futures.Mappings.hbm.xml" }; }
+ }
+
+ protected override string MappingsAssembly
+ {
+ get { return "NHibernate.Test"; }
+ }
+
+ [Test]
+ public void CanUseFutureQuery()
+ {
+ using (var s = sessions.OpenSession())
+ {
+ if (((SessionFactoryImpl)sessions)
+ .ConnectionProvider.Driver.SupportsMultipleQueries == false)
+ {
+ Assert.Ignore("Not applicable for dialects that do not support multiple queries");
+ }
+
+ var persons10 = s.CreateQuery("from Person")
+ .SetMaxResults(10)
+ .Future<Person>();
+ var persons5 = s.CreateQuery("from Person")
+ .SetMaxResults(5)
+ .Future<int>();
+
+ using (var logSpy = new SqlLogSpy())
+ {
+ foreach (var person in persons5)
+ {
+
+ }
+
+ foreach (var person in persons10)
+ {
+
+ }
+
+ var events = logSpy.Appender.GetEvents();
+ Assert.AreEqual(1, events.Length);
+ }
+ }
+ }
+
+ [Test]
+ public void TwoFuturesRunInTwoRoundTrips()
+ {
+ using (var s = sessions.OpenSession())
+ {
+ if (((SessionFactoryImpl)sessions)
+ .ConnectionProvider.Driver.SupportsMultipleQueries == false)
+ {
+ Assert.Ignore("Not applicable for dialects that do not support multiple queries");
+ }
+
+ using (var logSpy = new SqlLogSpy())
+ {
+ var persons10 = s.CreateQuery("from Person")
+ .SetMaxResults(10)
+ .Future<Person>();
+
+ foreach (var person in persons10) { } // fire first future round-trip
+
+ var persons5 = s.CreateQuery("from Person")
+ .SetMaxResults(5)
+ .Future<int>();
+
+ foreach (var person in persons5) { } // fire second future round-trip
+
+ var events = logSpy.Appender.GetEvents();
+ Assert.AreEqual(2, events.Length);
+ }
+ }
+ }
+
+ [Test]
+ public void CanCombineSingleFutureValueWithEnumerableFutures()
+ {
+ using (var s = sessions.OpenSession())
+ {
+ if (((SessionFactoryImpl)sessions)
+ .ConnectionProvider.Driver.SupportsMultipleQueries == false)
+ {
+ Assert.Ignore("Not applicable for dialects that do not support multiple queries");
+ }
+
+ var persons = s.CreateQuery("from Person")
+ .SetMaxResults(10)
+ .Future<Person>();
+
+ var personCount = s.CreateQuery("select count(*) from Person")
+ .FutureValue<long>();
+
+ using (var logSpy = new SqlLogSpy())
+ {
+ long count = personCount.Value;
+
+ foreach (var person in persons)
+ {
+ }
+
+ var events = logSpy.Appender.GetEvents();
+ Assert.AreEqual(1, events.Length);
+ }
+ }
+ }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-01-26 23:00:00 UTC (rev 4002)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-01-27 03:49:11 UTC (rev 4003)
@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
+ <ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7AEE5B37-C552-4E59-9B6F-88755BCB5070}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -373,6 +373,7 @@
<Compile Include="NHSpecificTest\BasicTimeFixture.cs" />
<Compile Include="NHSpecificTest\BugTestCase.cs" />
<Compile Include="NHSpecificTest\CollectionFixture.cs" />
+ <Compile Include="NHSpecificTest\Futures\FutureQueryFixture.cs" />
<Compile Include="NHSpecificTest\Futures\Fixture.cs" />
<Compile Include="NHSpecificTest\Futures\Person.cs" />
<Compile Include="NHSpecificTest\NH1274ExportExclude\Home.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|