private object ExecuteLinqNonQuery(LinqCommand linqCommand, EntitySession session, DataConnection connection) { var translCmd = GetTranslateLinqCommand(linqCommand); var dbCommand = CreateLinqDbCommand(connection, linqCommand, translCmd); var result = ExecuteDbCommand(dbCommand, connection, DbExecutionType.NonQuery); return result; }
public override void CommandExecuted(DataConnection connection, IDbCommand command, DbExecutionType executionType) { //If there is transaction started only for this command (see ExecuteCommand method above), then commit it if(command.CommandType == CommandType.StoredProcedure && executionType == DbExecutionType.Reader && command.Transaction != null && command.Transaction != connection.DbTransaction) { command.Transaction.Commit(); command.Transaction = null; } }
private IDbCommand CreateLinqDbCommand(DataConnection connection, LinqCommand linqCommand, TranslatedLinqCommand translatedCommand) { var cmd = connection.DbConnection.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = translatedCommand.Sql; foreach (var qParam in translatedCommand.Parameters) { var value = qParam.ReadValue(linqCommand.ParameterValues) ?? DBNull.Value; var dbParam = cmd.CreateParameter(); //DbModel.Driver.AddParameter(cmd, // dbParam.ParameterName = qParam.Name; //Value and parameter may need some tweaking, depending on server type DbModel.LinqSqlProvider.SetDbParameterValue(dbParam, value); cmd.Parameters.Add(dbParam); } return cmd; }
// Creates new connection or gets previously used from the session public DataConnection GetConnection(EntitySession session, ConnectionLifetime minLifetime = ConnectionLifetime.Operation, bool admin = false) { if (admin) return new DataConnection(session, this, minLifetime, true); var conn = session.CurrentConnection; if(conn != null) { if (conn.Lifetime < minLifetime) conn.Lifetime = minLifetime; return conn; } if (session.Context.DbConnectionMode == DbConnectionReuseMode.KeepOpen) minLifetime = ConnectionLifetime.Explicit; conn = new DataConnection(session, this, minLifetime, admin: admin); session.CurrentConnection = conn; //it will register it in disposables return conn; }
public object ExecuteDbCommand(IDbCommand command, DataConnection connection, DbExecutionType executionType, Func<IDataReader, int> resultsReader = null) { object result; IDataReader reader = null; connection.Session.SetLastCommand(command); try { command.Connection = connection.DbConnection; command.Transaction = connection.DbTransaction; var start = CurrentTickCount; int recordCount = -1; result = _driver.ExecuteCommand(command, executionType); if(executionType == DbExecutionType.Reader) { reader = (IDataReader)result; if(resultsReader != null) recordCount = resultsReader(reader); reader.Close(); } _driver.CommandExecuted(connection, command, executionType); var end = CurrentTickCount; var timeMs = (int)(end - start); LogCommand(connection.Session, command, timeMs, recordCount); return result; } catch(Exception ex) { // Important: in some cases exception on invalid SQL is not thrown immediately but is thrown later when we try to read the results // ex (MS SQL): WHERE "Name" LIKE 'ABC%' ESCAPE '' - with empty ESCAPE arg string. // So driver.ExecuteDbCommand does NOT catch it, it is thrown only here in call to resultsReader var dex = ex as DataAccessException; if(dex == null) dex = _driver.ConvertToDataAccessException(ex, command); if (connection.DbTransaction != null) { connection.Session.LogMessage(" -- Aborting transaction on error"); connection.Abort(); } connection.Session.LogMessage(" -- Failed command text: "); LogCommand(connection.Session, command, 0); ReviewExceptionAndAddInfo(dex); LogException(connection.Session, dex); if(reader != null) reader.Close(); throw dex; } finally { command.Transaction = null; command.Connection = null; } }
public UpdateSet(DataConnection connection, DateTime updateTime, IList<EntityRecord> records) { Connection = connection; Session = connection.Session; UpdateTime = updateTime; Id = Session.NextTransactionId; //Start explicit transaction only if we have more than one command to execute. UseTransaction = (records.Count + Session.ScheduledCommands.Count) > 1; AllRecords.AddRange(records); //check if we need sequencing var stt = Connection.Database.Settings; var useRefIntegrity = stt.ModelConfig.Options.IsSet(DbOptions.UseRefIntegrity); var canDeferIntegrCheck = stt.Driver.Supports(Driver.DbFeatures.DeferredConstraintCheck); var needSequencing = useRefIntegrity && !canDeferIntegrCheck; if(needSequencing) SequenceRecords(); //fills entity info set else { // fill entity Info set EntityInfos.UnionWith(records.Select(r => r.EntityInfo)); } UsesOutParams = AllRecords.Any(r => UsesOutParam(r)); }
public object ExecuteLinqSelect(LinqCommand linqCommand, EntitySession session, DataConnection conn) { var translCmd = GetTranslateLinqCommand(linqCommand); //Locks require ongoing transaction object result; var dbCommand = CreateLinqDbCommand(conn, linqCommand, translCmd); IList resultList = translCmd.ResultListCreator(); ExecuteDbCommand(dbCommand, conn, DbExecutionType.Reader, reader => { while(reader.Read()) { var row = translCmd.ObjectMaterializer(reader, session); //row might be null if authorization filtered it out or if it is empty value set from outer join if(row != null) resultList.Add(row); } return resultList.Count; }); //Post processor is extra selection op from the query (Fist,Single,Last) var postProcessor = translCmd.ResultsPostProcessor; if (postProcessor != null) result = postProcessor.ProcessRows(resultList); else result = resultList; return result; }
private void ExecuteScheduledCommands(DataConnection conn, EntitySession session, CommandSchedule schedule) { if (session.ScheduledCommands.Count == 0) return; foreach (var cmd in session.ScheduledCommands) if (cmd.Schedule == schedule) { ExecuteLinqNonQuery(cmd.Command, session, conn); } }
private void ApplyUpdate(DataConnection connection, EntityRecord record) { var cmdInfo = GetDbCommandForSave(record); Util.Check(cmdInfo != null, "Failed to find update/insert/delete command for entity {0}, status {1).", record.EntityInfo.Name, record.Status); try { var cmd = CreateDbCommand(cmdInfo, connection); SetCrudCommandParameterValues(cmdInfo, cmd, record); ExecuteDbCommand(cmd, connection, DbExecutionType.NonQuery); if(cmdInfo.PostUpdateActions.Count > 0) foreach(var action in cmdInfo.PostUpdateActions) action(connection, cmd, record); record.SubmitCount++; record.EntityInfo.SaveEvents.OnSubmittedChanges(record); } catch(Exception ex) { ex.AddValue("entity-command-name", cmdInfo.EntityCommand.CommandName); ex.AddValue("record", record); throw; } }
private void ReleaseConnection(DataConnection connection, bool inError = false) { if(connection == null) return; //close reader if exist if (connection.ActiveReader != null) { connection.ActiveReader.Close(); connection.ActiveReader = null; } if (inError) { if (connection.DbTransaction != null) connection.Abort(); connection.Close(); return; } //Do not close if there's a transaction, or it is a long-living connection if(connection.DbTransaction != null || connection.Lifetime == ConnectionLifetime.Explicit) return; //Otherwise, close it connection.Close(); if (connection.Session.CurrentConnection == connection) connection.Session.CurrentConnection = null; }
private IDbCommand CreateDbCommand(DbCommandInfo commandInfo, DataConnection connection) { var cmd = connection.DbConnection.CreateCommand(); cmd.Transaction = connection.DbTransaction; connection.Session.SetLastCommand(cmd); bool isSp = commandInfo.CommandType == CommandType.StoredProcedure && !connection.Session.Options.IsSet(EntitySessionOptions.DisableStoredProcs); if(isSp) { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = commandInfo.FullCommandName; } else { cmd.CommandType = CommandType.Text; cmd.CommandText = commandInfo.Sql; } //Create parameters collection if(commandInfo.IsTemplatedSql) { } else { for(int index = 0; index < commandInfo.Parameters.Count; index++) _driver.AddParameter(cmd, commandInfo.Parameters[index]); } return cmd; }