I want to inherit from NHibernate's SqlClientBatchingBatcher class exactly like this (code taken from TooManyRowsAffectedException with encrypted triggers):
public class NonBatchingBatcherWithoutVerification : SqlClientBatchingBatcher
{
public NonBatchingBatcherWithoutVerification(ConnectionManager connectionManager, IInterceptor interceptor) : base(connectionManager, interceptor)
{}
protected override void DoExecuteBatch(IDbCommand ps)
{
log.DebugFormat("Executing batch");
CheckReaders();
Prepare(currentBatch.BatchCommand);
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
{
Factory.Settings.SqlStatementLogger.LogBatchCommand(currentBatchCommandsLog.ToString());
currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
int rowsAffected = currentBatch.ExecuteNonQuery();
// Removed the following line
//Expectations.VerifyOutcomeBatched(totalExpectedRowsAffected, rowsAffected);
currentBatch.Dispose();
totalExpectedRowsAffected = 0;
currentBatch = new SqlClientSqlCommandSet();
}
}
Just notice some of the members accessed in the method here (like currentBatch or totalExpectedRowsAffected).
Well, it turns out these members are actually private in the superclass of the current NHibernate 3.3 source. So how do I effectively inherit the class without copying the whole thing? This is the unmodified NHibernate code of the class by the way:
public class SqlClientBatchingBatcher : AbstractBatcher
{
private int _batchSize;
private int _totalExpectedRowsAffected;
private SqlClientSqlCommandSet _currentBatch;
private StringBuilder _currentBatchCommandsLog;
private readonly int _defaultTimeout;
public SqlClientBatchingBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
: base(connectionManager, interceptor)
{
_batchSize = Factory.Settings.AdoBatchSize;
_defaultTimeout = PropertiesHelper.GetInt32(Cfg.Environment.CommandTimeout, Cfg.Environment.Properties, -1);
_currentBatch = CreateConfiguredBatch();
//we always create this, because we need to deal with a scenario in which
//the user change the logging configuration at runtime. Trying to put this
//behind an if(log.IsDebugEnabled) will cause a null reference exception
//at that point.
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
public override int BatchSize
{
get { return _batchSize; }
set { _batchSize = value; }
}
protected override int CountOfStatementsInCurrentBatch
{
get { return _currentBatch.CountOfCommands; }
}
public override void AddToBatch(IExpectation expectation)
{
_totalExpectedRowsAffected += expectation.ExpectedRowCount;
IDbCommand batchUpdate = CurrentCommand;
Driver.AdjustCommand(batchUpdate);
string lineWithParameters = null;
var sqlStatementLogger = Factory.Settings.SqlStatementLogger;
if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled)
{
lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate);
var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic);
lineWithParameters = formatStyle.Formatter.Format(lineWithParameters);
_currentBatchCommandsLog.Append("command ")
.Append(_currentBatch.CountOfCommands)
.Append(":")
.AppendLine(lineWithParameters);
}
if (Log.IsDebugEnabled)
{
Log.Debug("Adding to batch:" + lineWithParameters);
}
_currentBatch.Append((System.Data.SqlClient.SqlCommand) batchUpdate);
if (_currentBatch.CountOfCommands >= _batchSize)
{
ExecuteBatchWithTiming(batchUpdate);
}
}
protected override void DoExecuteBatch(IDbCommand ps)
{
Log.DebugFormat("Executing batch");
CheckReaders();
Prepare(_currentBatch.BatchCommand);
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
{
Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString());
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
int rowsAffected;
try
{
rowsAffected = _currentBatch.ExecuteNonQuery();
}
catch (DbException e)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command.");
}
Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowsAffected);
_currentBatch.Dispose();
_totalExpectedRowsAffected = 0;
_currentBatch = CreateConfiguredBatch();
}
private SqlClientSqlCommandSet CreateConfiguredBatch()
{
var result = new SqlClientSqlCommandSet();
if (_defaultTimeout > 0)
{
try
{
result.CommandTimeout = _defaultTimeout;
}
catch (Exception e)
{
if (Log.IsWarnEnabled)
{
Log.Warn(e.ToString());
}
}
}
return result;
}
}
Did I overlook something? Seems to a rather bad approach to copy the whole thing just to override all access to any private members. I just want to override one method!