public async Task <object> PerformInsertAsync(SqlCommandInfo insertSql, ISessionImplementor session, IBinder binder, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // NH-2145: Prevent connection releases between insert and select when we cannot perform // them as a single statement. Retrieving id most of the time relies on using the same connection. session.ConnectionManager.FlushBeginning(); try { try { // prepare and execute the insert var insert = await(session.Batcher.PrepareCommandAsync(insertSql.CommandType, insertSql.Text, insertSql.ParameterTypes, cancellationToken)).ConfigureAwait(false); try { await(binder.BindValuesAsync(insert, cancellationToken)).ConfigureAwait(false); await(session.Batcher.ExecuteNonQueryAsync(insert, cancellationToken)).ConfigureAwait(false); } finally { session.Batcher.CloseCommand(insert, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not insert: " + persister.GetInfoString(), insertSql.Text); } var selectSql = SelectSQL; using (session.BeginProcess()) { try { //fetch the generated id in a separate query var idSelect = await(session.Batcher.PrepareCommandAsync(CommandType.Text, selectSql, ParametersTypes, cancellationToken)).ConfigureAwait(false); try { await(BindParametersAsync(session, idSelect, binder, cancellationToken)).ConfigureAwait(false); var rs = await(session.Batcher.ExecuteReaderAsync(idSelect, cancellationToken)).ConfigureAwait(false); try { return(await(GetResultAsync(session, rs, binder.Entity, cancellationToken)).ConfigureAwait(false)); } finally { session.Batcher.CloseReader(rs); } } finally { session.Batcher.CloseCommand(idSelect, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not retrieve generated id after insert: " + persister.GetInfoString(), insertSql.Text); } } } finally { session.ConnectionManager.FlushEnding(); } }
protected async Task <List <object> > DoListAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled; var stopWatch = new Stopwatch(); if (statsEnabled) { stopWatch.Start(); } int rowCount = 0; var results = new List <object>(); var hydratedObjects = new List <object> [Translators.Count]; List <EntityKey[]>[] subselectResultKeys = new List <EntityKey[]> [Translators.Count]; bool[] createSubselects = new bool[Translators.Count]; try { using (var reader = await(resultSetsCommand.GetReaderAsync(_timeout, cancellationToken)).ConfigureAwait(false)) { if (log.IsDebugEnabled()) { log.Debug("Executing {0} queries", translators.Count); } for (int i = 0; i < translators.Count; i++) { ITranslator translator = Translators[i]; QueryParameters parameter = Parameters[i]; int entitySpan = translator.Loader.EntityPersisters.Length; hydratedObjects[i] = entitySpan > 0 ? new List <object>() : null; RowSelection selection = parameter.RowSelection; int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue; if (!dialect.SupportsLimitOffset || !translator.Loader.UseLimit(selection, dialect)) { await(Loader.Loader.AdvanceAsync(reader, selection, cancellationToken)).ConfigureAwait(false); } if (parameter.HasAutoDiscoverScalarTypes) { translator.Loader.AutoDiscoverTypes(reader); } LockMode[] lockModeArray = translator.Loader.GetLockModes(parameter.LockModes); EntityKey optionalObjectKey = Loader.Loader.GetOptionalObjectKey(parameter, session); createSubselects[i] = translator.Loader.IsSubselectLoadingEnabled; subselectResultKeys[i] = createSubselects[i] ? new List <EntityKey[]>() : null; translator.Loader.HandleEmptyCollections(parameter.CollectionKeys, reader, session); EntityKey[] keys = new EntityKey[entitySpan]; // we can reuse it each time if (log.IsDebugEnabled()) { log.Debug("processing result set"); } IList tempResults = new List <object>(); int count; for (count = 0; count < maxRows && await(reader.ReadAsync(cancellationToken)).ConfigureAwait(false); count++) { if (log.IsDebugEnabled()) { log.Debug("result set row: {0}", count); } rowCount++; object result = await(translator.Loader.GetRowFromResultSetAsync( reader, session, parameter, lockModeArray, optionalObjectKey, hydratedObjects[i], keys, true, cancellationToken)).ConfigureAwait(false); tempResults.Add(result); if (createSubselects[i]) { subselectResultKeys[i].Add(keys); keys = new EntityKey[entitySpan]; //can't reuse in this case } } if (log.IsDebugEnabled()) { log.Debug("done processing result set ({0} rows)", count); } results.Add(tempResults); if (log.IsDebugEnabled()) { log.Debug("Query {0} returned {1} results", i, tempResults.Count); } await(reader.NextResultAsync(cancellationToken)).ConfigureAwait(false); } for (int i = 0; i < translators.Count; i++) { ITranslator translator = translators[i]; QueryParameters parameter = parameters[i]; await(translator.Loader.InitializeEntitiesAndCollectionsAsync(hydratedObjects[i], reader, session, false, cancellationToken)).ConfigureAwait(false); if (createSubselects[i]) { translator.Loader.CreateSubselects(subselectResultKeys[i], parameter, session); } } } } catch (Exception sqle) { log.Error(sqle, "Failed to execute multi query: [{0}]", resultSetsCommand.Sql); throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "Failed to execute multi query", resultSetsCommand.Sql); } if (statsEnabled) { stopWatch.Stop(); session.Factory.StatisticsImplementor.QueryExecuted(string.Format("{0} queries (MultiQuery)", translators.Count), rowCount, stopWatch.Elapsed); } return(results); }
public override async Task <int> ExecuteAsync(QueryParameters parameters, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); CoordinateSharedCacheCleanup(session); await(CreateTemporaryTableIfNecessaryAsync(persister, session, cancellationToken)).ConfigureAwait(false); try { // First, save off the pertinent ids, saving the number of pertinent ids for return DbCommand ps = null; int resultCount; try { try { var paramsSpec = Walker.Parameters; var sqlString = FilterHelper.ExpandDynamicFilterParameters(idInsertSelect, paramsSpec, session); var sqlQueryParametersList = sqlString.GetParameters().ToList(); SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); ps = await(session.Batcher.PrepareCommandAsync(CommandType.Text, sqlString, parameterTypes, cancellationToken)).ConfigureAwait(false); foreach (var parameterSpecification in paramsSpec) { await(parameterSpecification.BindAsync(ps, sqlQueryParametersList, parameters, session, cancellationToken)).ConfigureAwait(false); } resultCount = await(session.Batcher.ExecuteNonQueryAsync(ps, cancellationToken)).ConfigureAwait(false); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not insert/select ids for bulk delete", idInsertSelect); } // Start performing the deletes for (int i = 0; i < deletes.Length; i++) { try { try { ps = await(session.Batcher.PrepareCommandAsync(CommandType.Text, deletes[i], Array.Empty <SqlType>(), cancellationToken)).ConfigureAwait(false); await(session.Batcher.ExecuteNonQueryAsync(ps, cancellationToken)).ConfigureAwait(false); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "error performing bulk delete", deletes[i]); } } return(resultCount); } finally { await(DropTemporaryTableIfNecessaryAsync(persister, session, cancellationToken)).ConfigureAwait(false); } }
public object PerformInsert(SqlCommandInfo insertSql, ISessionImplementor session, IBinder binder) { // NH-2145: Prevent connection releases between insert and select when we cannot perform // them as a single statement. Retrieving id most of the time relies on using the same connection. session.ConnectionManager.FlushBeginning(); try { try { // prepare and execute the insert var insert = session.Batcher.PrepareCommand(insertSql.CommandType, insertSql.Text, insertSql.ParameterTypes); try { binder.BindValues(insert); session.Batcher.ExecuteNonQuery(insert); } finally { session.Batcher.CloseCommand(insert, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not insert: " + persister.GetInfoString(), insertSql.Text); } var selectSql = SelectSQL; using (new SessionIdLoggingContext(session.SessionId)) { try { //fetch the generated id in a separate query var idSelect = session.Batcher.PrepareCommand(CommandType.Text, selectSql, ParametersTypes); try { BindParameters(session, idSelect, binder.Entity); var rs = session.Batcher.ExecuteReader(idSelect); try { return(GetResult(session, rs, binder.Entity)); } finally { session.Batcher.CloseReader(rs); } } finally { session.Batcher.CloseCommand(idSelect, null); } } catch (DbException sqle) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "could not retrieve generated id after insert: " + persister.GetInfoString(), insertSql.Text); } } } finally { session.ConnectionManager.FlushEnding(); } }
protected override int DoUpdateRows(object id, IPersistentCollection collection, ISessionImplementor session) { // we finish all the "removes" first to take care of possible unique // constraints and so that we can take better advantage of batching try { const int offset = 0; int count = 0; if (RowDeleteEnabled) { IExpectation deleteExpectation = Expectations.AppropriateExpectation(DeleteCheckStyle); bool useBatch = deleteExpectation.CanBeBatched; SqlCommandInfo sql = SqlDeleteRowString; IDbCommand st = null; // update removed rows fks to null try { int i = 0; IEnumerable entries = collection.Entries(this); foreach (object entry in entries) { if (collection.NeedsUpdating(entry, i, ElementType)) { // will still be issued when it used to be null if (useBatch) { st = session.Batcher.PrepareBatchCommand(SqlDeleteRowString.CommandType, sql.Text, SqlDeleteRowString.ParameterTypes); } else { st = session.Batcher.PrepareCommand(SqlDeleteRowString.CommandType, sql.Text, SqlDeleteRowString.ParameterTypes); } int loc = WriteKey(st, id, offset, session); WriteElementToWhere(st, collection.GetSnapshotElement(entry, i), loc, session); if (useBatch) { session.Batcher.AddToBatch(deleteExpectation); } else { deleteExpectation.VerifyOutcomeNonBatched(session.Batcher.ExecuteNonQuery(st), st); } count++; } i++; } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch && st != null) { session.Batcher.CloseCommand(st, null); } } } if (RowInsertEnabled) { IExpectation insertExpectation = Expectations.AppropriateExpectation(InsertCheckStyle); //bool callable = InsertCallable; bool useBatch = insertExpectation.CanBeBatched; SqlCommandInfo sql = SqlInsertRowString; IDbCommand st = null; // now update all changed or added rows fks try { int i = 0; IEnumerable entries = collection.Entries(this); foreach (object entry in entries) { if (collection.NeedsUpdating(entry, i, ElementType)) { if (useBatch) { st = session.Batcher.PrepareBatchCommand(SqlInsertRowString.CommandType, sql.Text, SqlInsertRowString.ParameterTypes); } else { st = session.Batcher.PrepareCommand(SqlInsertRowString.CommandType, sql.Text, SqlInsertRowString.ParameterTypes); } //offset += insertExpectation.Prepare(st, Factory.ConnectionProvider.Driver); int loc = WriteKey(st, id, offset, session); if (HasIndex && !indexContainsFormula) { loc = WriteIndexToWhere(st, collection.GetIndex(entry, i, this), loc, session); } WriteElementToWhere(st, collection.GetElement(entry), loc, session); if (useBatch) { session.Batcher.AddToBatch(insertExpectation); } else { insertExpectation.VerifyOutcomeNonBatched(session.Batcher.ExecuteNonQuery(st), st); } count++; } i++; } } catch (Exception e) { if (useBatch) { session.Batcher.AbortBatch(e); } throw; } finally { if (!useBatch && st != null) { session.Batcher.CloseCommand(st, null); } } } return(count); } catch (DbException sqle) { throw ADOExceptionHelper.Convert(SQLExceptionConverter, sqle, "could not update collection rows: " + MessageHelper.InfoString(this, id)); } }
public void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork work, bool transacted) { DbConnection connection = null; DbTransaction trans = null; // bool wasAutoCommit = false; try { // We make an exception for SQLite and use the session's connection, // since SQLite only allows one connection to the database. if (session.Factory.Dialect is SQLiteDialect) { connection = session.Connection; } else { connection = session.Factory.ConnectionProvider.GetConnection(); } if (transacted) { trans = connection.BeginTransaction(); // TODO NH: a way to read the autocommit state is needed //if (TransactionManager.GetAutoCommit(connection)) //{ // wasAutoCommit = true; // TransactionManager.SetAutoCommit(connection, false); //} } work.DoWork(connection, trans); if (transacted) { trans.Commit(); //TransactionManager.Commit(connection); } } catch (Exception t) { using (new SessionIdLoggingContext(session.SessionId)) { try { if (trans != null && connection.State != ConnectionState.Closed) { trans.Rollback(); } } catch (Exception ignore) { isolaterLog.Debug("unable to release connection on exception [" + ignore + "]"); } if (t is HibernateException) { throw; } else if (t is DbException) { throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, t, "error performing isolated work"); } else { throw new HibernateException("error performing isolated work", t); } } } finally { //if (transacted && wasAutoCommit) //{ // try // { // // TODO NH: reset autocommit // // TransactionManager.SetAutoCommit(connection, true); // } // catch (Exception) // { // log.Debug("was unable to reset connection back to auto-commit"); // } //} if (session.Factory.Dialect is SQLiteDialect == false) { session.Factory.ConnectionProvider.CloseConnection(connection); } } }
public override int Execute(QueryParameters parameters, ISessionImplementor session) { CoordinateSharedCacheCleanup(session); CreateTemporaryTableIfNecessary(persister, session); try { // First, save off the pertinent ids, saving the number of pertinent ids for return DbCommand ps = null; int resultCount; try { try { var paramsSpec = Walker.Parameters; var sqlQueryParametersList = idInsertSelect.GetParameters().ToList(); SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes); foreach (var parameterSpecification in paramsSpec) { parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); } resultCount = session.Batcher.ExecuteNonQuery(ps); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not insert/select ids for bulk delete", idInsertSelect); } // Start performing the deletes for (int i = 0; i < deletes.Length; i++) { try { try { ps = session.Batcher.PrepareCommand(CommandType.Text, deletes[i], new SqlType[0]); session.Batcher.ExecuteNonQuery(ps); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "error performing bulk delete", deletes[i]); } } return(resultCount); } finally { DropTemporaryTableIfNecessary(persister, session); } }
public override int Execute(QueryParameters parameters, ISessionImplementor session) { CoordinateSharedCacheCleanup(session); CreateTemporaryTableIfNecessary(persister, session); try { // First, save off the pertinent ids, as the return value DbCommand ps = null; int resultCount; try { try { int parameterStart = Walker.NumberOfParametersInSetClause; IList <IParameterSpecification> allParams = Walker.Parameters; List <IParameterSpecification> whereParams = (new List <IParameterSpecification>(allParams)).GetRange( parameterStart, allParams.Count - parameterStart); var sqlQueryParametersList = idInsertSelect.GetParameters().ToList(); SqlType[] parameterTypes = whereParams.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes); foreach (var parameterSpecification in whereParams) { parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); } resultCount = session.Batcher.ExecuteNonQuery(ps); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not insert/select ids for bulk update", idInsertSelect); } // Start performing the updates for (int i = 0; i < updates.Length; i++) { if (updates[i] == null) { continue; } try { try { var sqlQueryParametersList = updates[i].GetParameters().ToList(); var paramsSpec = hqlParameters[i]; SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); ps = session.Batcher.PrepareCommand(CommandType.Text, updates[i], parameterTypes); foreach (var parameterSpecification in paramsSpec) { parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); } session.Batcher.ExecuteNonQuery(ps); } finally { if (ps != null) { session.Batcher.CloseCommand(ps, null); } } } catch (DbException e) { throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "error performing bulk update", updates[i]); } } return(resultCount); } finally { DropTemporaryTableIfNecessary(persister, session); } }
protected ArrayList DoList() { bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled; var stopWatch = new Stopwatch(); if (statsEnabled) { stopWatch.Start(); } int rowCount = 0; ArrayList results = new ArrayList(); ArrayList[] hydratedObjects = new ArrayList[Translators.Count]; List <EntityKey[]>[] subselectResultKeys = new List <EntityKey[]> [Translators.Count]; bool[] createSubselects = new bool[Translators.Count]; try { using (var reader = resultSetsCommand.GetReader(commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null)) { if (log.IsDebugEnabled) { log.DebugFormat("Executing {0} queries", translators.Count); } for (int i = 0; i < translators.Count; i++) { ITranslator translator = Translators[i]; QueryParameters parameter = Parameters[i]; int entitySpan = translator.Loader.EntityPersisters.Length; hydratedObjects[i] = entitySpan > 0 ? new ArrayList() : null; RowSelection selection = parameter.RowSelection; int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue; if (!dialect.SupportsLimitOffset || !translator.Loader.UseLimit(selection, dialect)) { Loader.Loader.Advance(reader, selection); } LockMode[] lockModeArray = translator.Loader.GetLockModes(parameter.LockModes); EntityKey optionalObjectKey = Loader.Loader.GetOptionalObjectKey(parameter, session); createSubselects[i] = translator.Loader.IsSubselectLoadingEnabled; subselectResultKeys[i] = createSubselects[i] ? new List <EntityKey[]>() : null; translator.Loader.HandleEmptyCollections(parameter.CollectionKeys, reader, session); EntityKey[] keys = new EntityKey[entitySpan]; // we can reuse it each time if (log.IsDebugEnabled) { log.Debug("processing result set"); } IList tempResults = new ArrayList(); int count; for (count = 0; count < maxRows && reader.Read(); count++) { if (log.IsDebugEnabled) { log.Debug("result set row: " + count); } rowCount++; object result = translator.Loader.GetRowFromResultSet( reader, session, parameter, lockModeArray, optionalObjectKey, hydratedObjects[i], keys, true); tempResults.Add(result); if (createSubselects[i]) { subselectResultKeys[i].Add(keys); keys = new EntityKey[entitySpan]; //can't reuse in this case } } if (log.IsDebugEnabled) { log.Debug(string.Format("done processing result set ({0} rows)", count)); } results.Add(tempResults); if (log.IsDebugEnabled) { log.DebugFormat("Query {0} returned {1} results", i, tempResults.Count); } reader.NextResult(); } for (int i = 0; i < translators.Count; i++) { ITranslator translator = translators[i]; QueryParameters parameter = parameters[i]; translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false); if (createSubselects[i]) { translator.Loader.CreateSubselects(subselectResultKeys[i], parameter, session); } } } } catch (Exception sqle) { var message = string.Format("Failed to execute multi query: [{0}]", resultSetsCommand.Sql); log.Error(message, sqle); throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, "Failed to execute multi query", resultSetsCommand.Sql); } if (statsEnabled) { stopWatch.Stop(); session.Factory.StatisticsImplementor.QueryExecuted(string.Format("{0} queries (MultiQuery)", translators.Count), rowCount, stopWatch.Elapsed); } return(results); }