Ejemplo n.º 1
0
        private void ExecuteBatchMultipleCommands(UpdateSet updateSet)
        {
            //Note: for multiple commands, we cannot include trans statements into batch commands, like add 'Begin Trans' to the first command
            //  and 'Commit' to the last command - this will fail. We start/commit trans using separate calls
            // Also, we have to manage connection explicitly, to start/commit transaction
            var conn = updateSet.Connection;

            try {
                var inNewTrans = conn.DbTransaction == null;
                if (inNewTrans)
                {
                    conn.BeginTransaction(commitOnSave: true);
                }
                foreach (var batchCmd in updateSet.BatchCommands)
                {
                    ExecuteDbCommand(batchCmd.DbCommand, conn, DbExecutionType.NonQuery);
                    if (batchCmd.HasActions)
                    {
                        foreach (var action in batchCmd.GetPostActions())
                        {
                            action();
                        }
                    }
                }//foreach
                if (inNewTrans)
                {
                    conn.Commit();
                }
                ReleaseConnection(conn);
            } catch {
                ReleaseConnection(conn, inError: true);
                throw;
            }
        }
Ejemplo n.º 2
0
        // Note: scheduled commands are already in batch commands
        private void SaveChangesInBatchMode(UpdateSet updateSet)
        {
            var session         = updateSet.Session;
            var postExecActions = new List <Action>();
            var batchBuilder    = new DbBatchCommandSetBuilder(this, updateSet);

            batchBuilder.Build();
            LogComment(session, "-- BEGIN BATCH ({0} rows, {1} batch command(s)) ---------------------------", updateSet.AllRecords.Count, updateSet.BatchCommands.Count);
            if (updateSet.BatchCommands.Count == 1)
            {
                ExecuteBatchSingleCommand(updateSet);
            }
            else
            {
                ExecuteBatchMultipleCommands(updateSet);
            }
            LogComment(session, "-- END BATCH --------------------------------------\r\n");
            //execute post-execute actions; it is usually handling output parameter values
            // Finalize records after update
            foreach (var rec in updateSet.AllRecords)
            {
                rec.CustomTag = null; //clear temp ref that batch process has set
                rec.SubmitCount++;
                rec.EntityInfo.SaveEvents.OnSubmittedChanges(rec);
            }
        }
Ejemplo n.º 3
0
        private void ExecuteBatchSingleCommand(UpdateSet updateSet)
        {
            var conn = updateSet.Connection;

            try {
                var batchCmd = updateSet.BatchCommands[0];
                var dbCmd    = batchCmd.DbCommand;
                if (conn.DbTransaction == null) //surround it with beginTrans/commit
                {
                    dbCmd.CommandText = string.Format("{0}\r\n{1}\r\n{2}", _driver.BatchBeginTransaction, dbCmd.CommandText, _driver.BatchCommitTransaction);
                }
                ExecuteDbCommand(dbCmd, conn, DbExecutionType.NonQuery);
                if (batchCmd.HasActions)
                {
                    foreach (var action in batchCmd.GetPostActions())
                    {
                        action();
                    }
                }
                ReleaseConnection(conn);
            } catch {
                ReleaseConnection(conn, inError: true);
                throw;
            }
        }
Ejemplo n.º 4
0
        public void SaveChanges(EntitySession session)
        {
            if (session.HasChanges())
            {
                var records   = session.RecordsChanged.Where(rec => ShouldUpdate(rec)).ToList();
                var conn      = GetConnection(session);
                var updateSet = new UpdateSet(conn, _timeService.UtcNow, records);
                var batchMode = ShouldUseBatchMode(updateSet);
                if (batchMode)
                {
                    SaveChangesInBatchMode(updateSet);
                }
                else
                {
                    SaveChangesNoBatch(session, updateSet);
                }
            }
            //commit if we have session connection with transaction and CommitOnSave
            var sConn = session.CurrentConnection;

            if (sConn != null)
            {
                if (sConn.DbTransaction != null && sConn.Flags.IsSet(ConnectionFlags.CommitOnSave))
                {
                    sConn.Commit();
                }
                if (sConn.Lifetime != ConnectionLifetime.Explicit)
                {
                    ReleaseConnection(sConn);
                }
            }
            session.ScheduledCommands.Clear();
        }
Ejemplo n.º 5
0
 public DbBatchCommandSetBuilder(Database db, UpdateSet updateSet)
 {
     _db = db;
       _driver = _db.DbModel.Driver;
       _updateSet = updateSet;
       // Clear identity holders in record.CustomTag
       if (_updateSet.UsesOutParams)
     foreach (var rec in updateSet.AllRecords)
       rec.CustomTag = null;
 }
Ejemplo n.º 6
0
 public DbBatchCommandSetBuilder(Database db, UpdateSet updateSet)
 {
     _db        = db;
     _driver    = _db.DbModel.Driver;
     _updateSet = updateSet;
     // Clear identity holders in record.CustomTag
     if (_updateSet.UsesOutParams)
     {
         foreach (var rec in updateSet.AllRecords)
         {
             rec.CustomTag = null;
         }
     }
 }
Ejemplo n.º 7
0
 private void ExecuteBatchSingleCommand(UpdateSet updateSet)
 {
     var conn = updateSet.Connection;
       try {
     var batchCmd = updateSet.BatchCommands[0];
     var dbCmd = batchCmd.DbCommand;
     if (conn.DbTransaction == null) //surround it with beginTrans/commit
       dbCmd.CommandText = string.Format("{0}\r\n{1}\r\n{2}", _driver.BatchBeginTransaction, dbCmd.CommandText, _driver.BatchCommitTransaction);
     ExecuteDbCommand(dbCmd, conn, DbExecutionType.NonQuery);
     if (batchCmd.HasActions)
       foreach (var action in batchCmd.GetPostActions())
     action();
     ReleaseConnection(conn);
       } catch {
     ReleaseConnection(conn, inError: true);
     throw;
       }
 }
Ejemplo n.º 8
0
        // Checks if batch is needed (record count > 1); and driver supports batch mode, and if batch is not disabled;
        // If there are any out params for CRUD stored procs (identity, timestamp) then driver should out param for batch mode
        // MS SQL supports batch with output params; SQL CE does not support batch at all - one statement at a time.
        // MySql and Postgres support batch, but there are some troubles in using output parameters inside the batch,
        // so for these drivers batch OutParamsInBatchMode is not set, so we do not use batch mode if there are any.
        private bool ShouldUseBatchMode(UpdateSet updateSet)
        {
            var totalCount = updateSet.AllRecords.Count + updateSet.Session.ScheduledCommands.Count;

            if (totalCount > 1 && Settings.ModelConfig.Options.IsSet(DbOptions.UseBatchMode))
            {
                //Probably we should use batch mode; check if it is disabled or stored procs are disabled
                if (updateSet.Session.Options.IsSet(EntitySessionOptions.DisableBatch | EntitySessionOptions.DisableStoredProcs))
                {
                    return(false);
                }
                // check if there any out params
                if (updateSet.UsesOutParams && !_driver.Supports(DbFeatures.OutParamsInBatchedUpdates))
                {
                    return(false);
                }
                //otherwise return true
                return(true);
            }
            return(false);
        }
Ejemplo n.º 9
0
 // Note: scheduled commands are already in batch commands
 private void SaveChangesInBatchMode(UpdateSet updateSet)
 {
     var session = updateSet.Session;
       var postExecActions = new List<Action>();
       var batchBuilder = new DbBatchCommandSetBuilder(this, updateSet);
       batchBuilder.Build();
       LogComment(session, "-- BEGIN BATCH ({0} rows, {1} batch command(s)) ---------------------------", updateSet.AllRecords.Count, updateSet.BatchCommands.Count);
       if (updateSet.BatchCommands.Count == 1) {
     ExecuteBatchSingleCommand(updateSet);
       } else {
     ExecuteBatchMultipleCommands(updateSet);
       }
       LogComment(session, "-- END BATCH --------------------------------------\r\n");
       //execute post-execute actions; it is usually handling output parameter values
       // Finalize records after update
       foreach (var rec in updateSet.AllRecords) {
     rec.CustomTag = null; //clear temp ref that batch process has set
     rec.SubmitCount++;
     rec.EntityInfo.SaveEvents.OnSubmittedChanges(rec);
       }
 }
Ejemplo n.º 10
0
 private void ExecuteBatchMultipleCommands(UpdateSet updateSet)
 {
     //Note: for multiple commands, we cannot include trans statements into batch commands, like add 'Begin Trans' to the first command
       //  and 'Commit' to the last command - this will fail. We start/commit trans using separate calls
       // Also, we have to manage connection explicitly, to start/commit transaction
       var conn = updateSet.Connection;
       try {
     var inNewTrans = conn.DbTransaction == null;
     if (inNewTrans)
       conn.BeginTransaction(commitOnSave: true);
     foreach (var batchCmd in updateSet.BatchCommands) {
       ExecuteDbCommand(batchCmd.DbCommand, conn, DbExecutionType.NonQuery);
       if (batchCmd.HasActions)
     foreach (var action in batchCmd.GetPostActions())
       action();
     }//foreach
     if (inNewTrans)
       conn.Commit();
     ReleaseConnection(conn);
       } catch {
     ReleaseConnection(conn, inError: true);
     throw;
       }
 }
Ejemplo n.º 11
0
        private void SaveChangesNoBatch(EntitySession session, UpdateSet updateSet)
        {
            var conn      = updateSet.Connection;
            var withTrans = conn.DbTransaction == null && updateSet.UseTransaction;

            try {
                var start = CurrentTickCount;
                if (withTrans)
                {
                    conn.BeginTransaction(commitOnSave: true);
                }
                //execute commands
                if (session.ScheduledCommands.Count > 0)
                {
                    ExecuteScheduledCommands(conn, session, CommandSchedule.TransactionStart);
                }
                //Apply record updates
                foreach (var rec in updateSet.AllRecords)
                {
                    ApplyUpdate(conn, rec);
                }
                //Execute scheduled commands
                if (session.ScheduledCommands.Count > 0)
                {
                    ExecuteScheduledCommands(conn, session, CommandSchedule.TransactionEnd);
                }
                if (conn.DbTransaction != null && conn.Flags.IsSet(ConnectionFlags.CommitOnSave))
                {
                    conn.Commit();
                }
                ReleaseConnection(conn);
            } catch {
                ReleaseConnection(conn, inError: true);
                throw;
            }
        }
Ejemplo n.º 12
0
 private void SaveChangesNoBatch(EntitySession session, UpdateSet updateSet)
 {
     var conn = updateSet.Connection;
       var withTrans = conn.DbTransaction == null && updateSet.UseTransaction;
       try {
     var start = CurrentTickCount;
     if(withTrans)
       conn.BeginTransaction(commitOnSave: true);
     //execute commands
     if (session.ScheduledCommands.Count > 0)
       ExecuteScheduledCommands(conn, session, CommandSchedule.TransactionStart);
     //Apply record updates
     foreach(var rec in updateSet.AllRecords)
       ApplyUpdate(conn, rec);
     //Execute scheduled commands
     if (session.ScheduledCommands.Count > 0)
       ExecuteScheduledCommands(conn, session, CommandSchedule.TransactionEnd);
     if (conn.DbTransaction != null && conn.Flags.IsSet(ConnectionFlags.CommitOnSave))
       conn.Commit();
     ReleaseConnection(conn);
       } catch {
     ReleaseConnection(conn, inError: true);
     throw;
       }
 }
Ejemplo n.º 13
0
 public void SaveChanges(EntitySession session)
 {
     if (session.HasChanges()) {
     var records = session.RecordsChanged.Where(rec => ShouldUpdate(rec)).ToList();
     var conn = GetConnection(session);
     var updateSet = new UpdateSet(conn, _timeService.UtcNow, records);
     var batchMode = ShouldUseBatchMode(updateSet);
     if (batchMode)
       SaveChangesInBatchMode(updateSet);
     else
       SaveChangesNoBatch(session, updateSet);
       }
       //commit if we have session connection with transaction and CommitOnSave
       var sConn = session.CurrentConnection;
       if (sConn != null) {
     if (sConn.DbTransaction != null && sConn.Flags.IsSet(ConnectionFlags.CommitOnSave))
       sConn.Commit();
     if (sConn.Lifetime != ConnectionLifetime.Explicit)
       ReleaseConnection(sConn);
       }
       session.ScheduledCommands.Clear();
 }
Ejemplo n.º 14
0
 // Checks if batch is needed (record count > 1); and driver supports batch mode, and if batch is not disabled;
 // If there are any out params for CRUD stored procs (identity, timestamp) then driver should out param for batch mode
 // MS SQL supports batch with output params; SQL CE does not support batch at all - one statement at a time.
 // MySql and Postgres support batch, but there are some troubles in using output parameters inside the batch,
 // so for these drivers batch OutParamsInBatchMode is not set, so we do not use batch mode if there are any.
 private bool ShouldUseBatchMode(UpdateSet updateSet)
 {
     var totalCount = updateSet.AllRecords.Count + updateSet.Session.ScheduledCommands.Count;
       if (totalCount > 1 && Settings.ModelConfig.Options.IsSet(DbOptions.UseBatchMode)) {
     //Probably we should use batch mode; check if it is disabled or stored procs are disabled
     if(updateSet.Session.Options.IsSet(EntitySessionOptions.DisableBatch | EntitySessionOptions.DisableStoredProcs))
       return false;
     // check if there any out params
     if(updateSet.UsesOutParams && !_driver.Supports(DbFeatures.OutParamsInBatchedUpdates))
       return false;
     //otherwise return true
     return true;
       }
       return false;
 }