From: <aye...@us...> - 2009-05-22 05:38:22
|
Revision: 4353 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4353&view=rev Author: ayenderahien Date: 2009-05-22 05:38:20 +0000 (Fri, 22 May 2009) Log Message: ----------- NH-1790 - allowing SqlClientBatchingBatcher to batch non identical statements. This means a nice perf improvement because we can put more stuff into a batch, but it should be noted that we aren't batching across different statement types. That is, we will batch all inserts, but we will not batch inserts & updates. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcher.cs trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcherFactory.cs trunk/nhibernate/src/NHibernate.Test/Ado/BatcherFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.cs trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.hbm.xml Modified: trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2009-05-22 00:52:05 UTC (rev 4352) +++ trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2009-05-22 05:38:20 UTC (rev 4353) @@ -148,9 +148,7 @@ public IDbCommand PrepareCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) { - // a new IDbCommand is being prepared and a new (potential) batch - // started - so execute the current batch of commands. - ExecuteBatch(); + OnPreparedCommand(); // do not actually prepare the Command here - instead just generate it because // if the command is associated with an ADO.NET Transaction/Connection while @@ -159,6 +157,13 @@ return Generate(type, sql, parameterTypes); } + protected virtual void OnPreparedCommand() + { + // a new IDbCommand is being prepared and a new (potential) batch + // started - so execute the current batch of commands. + ExecuteBatch(); + } + public IDbCommand PrepareQueryCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) { // do not actually prepare the Command here - instead just generate it because Modified: trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcher.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcher.cs 2009-05-22 00:52:05 UTC (rev 4352) +++ trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcher.cs 2009-05-22 05:38:20 UTC (rev 4353) @@ -74,5 +74,12 @@ totalExpectedRowsAffected = 0; currentBatch = new SqlClientSqlCommandSet(); } + + protected override void OnPreparedCommand() + { + // SQL Server batching can handle several different commands, and + // that gives us a nice perf boost when mixing different queries for + // batching + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcherFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcherFactory.cs 2009-05-22 00:52:05 UTC (rev 4352) +++ trunk/nhibernate/src/NHibernate/AdoNet/SqlClientBatchingBatcherFactory.cs 2009-05-22 05:38:20 UTC (rev 4353) @@ -2,7 +2,7 @@ namespace NHibernate.AdoNet { - internal class SqlClientBatchingBatcherFactory : IBatcherFactory + public class SqlClientBatchingBatcherFactory : IBatcherFactory { public virtual IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor) { Added: trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.cs 2009-05-22 05:38:20 UTC (rev 4353) @@ -0,0 +1,9 @@ +namespace NHibernate.Test.Ado +{ + public class AlmostSimple + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual double Weight { get; set; } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Ado/AlmostSimple.hbm.xml 2009-05-22 05:38:20 UTC (rev 4353) @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.Ado"> + + <class name="AlmostSimple"> + <id name="Id"/> + <property name="Name"/> + <property name="Weight"/> + </class> + +</hibernate-mapping> \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Ado/BatcherFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Ado/BatcherFixture.cs 2009-05-22 00:52:05 UTC (rev 4352) +++ trunk/nhibernate/src/NHibernate.Test/Ado/BatcherFixture.cs 2009-05-22 05:38:20 UTC (rev 4353) @@ -1,6 +1,7 @@ using System.Collections; using NHibernate.AdoNet; using NHibernate.Cfg; +using NHibernate.Dialect; using NUnit.Framework; namespace NHibernate.Test.Ado @@ -15,7 +16,7 @@ protected override IList Mappings { - get { return new[] { "Ado.VerySimple.hbm.xml" }; } + get { return new[] { "Ado.VerySimple.hbm.xml", "Ado.AlmostSimple.hbm.xml" }; } } protected override void Configure(Configuration configuration) @@ -47,6 +48,7 @@ using (s.BeginTransaction()) { s.CreateQuery("delete from VerySimple").ExecuteUpdate(); + s.CreateQuery("delete from AlmostSimple").ExecuteUpdate(); s.Transaction.Commit(); } } @@ -74,7 +76,7 @@ var vs1 = s.Get<VerySimple>(1); var vs2 = s.Get<VerySimple>(2); vs1.Weight -= 10; - vs1.Weight -= 1; + vs2.Weight -= 1; sessions.Statistics.Clear(); s.Update(vs1); s.Update(vs2); @@ -86,6 +88,45 @@ } [Test] + [Description("SqlClient: The batcher should run all different INSERT queries in only one roundtrip.")] + public void SqlClientOneRoundTripForUpdateAndInsert() + { + if (sessions.Settings.BatcherFactory is SqlClientBatchingBatcherFactory == false) + Assert.Ignore("This test is for SqlClientBatchingBatcher only"); + + FillDb(); + + using(var sqlLog = new SqlLogSpy()) + using (ISession s = sessions.OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + s.Save(new VerySimple + { + Name = "test441", + Weight = 894 + }); + + s.Save(new AlmostSimple + { + Name = "test441", + Weight = 894 + }); + + tx.Commit(); + + var log = sqlLog.GetWholeLog(); + //log should only contain NHibernate.SQL once, because that means + //that we ony generated a single batch (NHibernate.SQL log will output + //once per batch) + Assert.AreEqual(0, log.IndexOf("NHibernate.SQL"), "log should start with NHibernate.SQL"); + Assert.AreEqual(-1, log.IndexOf("NHibernate.SQL", "NHibernate.SQL".Length), "NHibernate.SQL should only appear once in the log"); + } + + Cleanup(); + } + + + [Test] [Description("The batcher should run all DELETE queries in only one roundtrip.")] public void OneRoundTripDelete() { Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-05-22 00:52:05 UTC (rev 4352) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-05-22 05:38:20 UTC (rev 4353) @@ -74,6 +74,7 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="Ado\AlmostSimple.cs" /> <Compile Include="Ado\BatcherFixture.cs" /> <Compile Include="Ado\VerySimple.cs" /> <Compile Include="Any\Address.cs" /> @@ -1822,6 +1823,7 @@ <EmbeddedResource Include="Deletetransient\Person.hbm.xml" /> <EmbeddedResource Include="BulkManipulation\SimpleClass.hbm.xml" /> <EmbeddedResource Include="Ado\VerySimple.hbm.xml" /> + <EmbeddedResource Include="Ado\AlmostSimple.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> <EmbeddedResource Include="NHSpecificTest\NH1756\Mappings.hbm.xml" /> <EmbeddedResource Include="LazyProperty\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |