Example #1
0
        public void SaveChanges(EntitySession session)
        {
            if (session.HasChanges())
            {
                var conn      = GetConnection(session);
                var updateSet = new DbUpdateSet(session, this.DbModel, conn);
                var batchMode = ShouldUseBatchMode(updateSet);
                if (batchMode)
                {
                    SaveChangesInBatchMode(updateSet);
                }
                else
                {
                    SaveChangesNoBatch(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(DbConnectionFlags.CommitOnSave))
                {
                    sConn.Commit();
                }
                if (sConn.Lifetime != DbConnectionLifetime.Explicit)
                {
                    ReleaseConnection(sConn);
                }
            }
            session.ScheduledCommandsAtStart = null;
            session.ScheduledCommandsAtEnd   = null;
        }
Example #2
0
        // Note: scheduled commands are already in batch commands
        private void SaveChangesInBatchMode(DbUpdateSet updateSet)
        {
            var batchBuilder = new DbBatchBuilder(this);
            var batch        = batchBuilder.Build(updateSet);

            LogComment(updateSet.Session, "-- BEGIN BATCH ({0} rows, {1} batch command(s)) ---------------------------",
                       updateSet.Records.Count, batch.Commands.Count);
            if (batch.Commands.Count == 1)
            {
                ExecuteBatchSingleCommand(batch);
            }
            else
            {
                ExecuteBatchMultipleCommands(batch);
            }


            LogComment(updateSet.Session, "-- END BATCH --------------------------------------\r\n");

            var postExecActions = new List <Action>();

            var session = updateSet.Session;

            //execute post-execute actions; it is usually handling output parameter values
            // Finalize records after update
            foreach (var rec in updateSet.Records)
            {
                rec.EntityInfo.SaveEvents.OnSubmittedChanges(rec);
            }
        }
Example #3
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(DbUpdateSet updateSet)
        {
            var canUseBatch = Settings.Driver.Supports(DbFeatures.BatchedUpdates) && Settings.ModelConfig.Options.IsSet(DbOptions.UseBatchMode);

            if (!canUseBatch)
            {
                return(false);
            }
            var totalCount = updateSet.Records.Count + updateSet.Session.ScheduledCommandsCount();

            if (totalCount <= 1)
            {
                return(false);
            }
            var options = updateSet.Session.Options;

            if (options.IsSet(EntitySessionOptions.DisableBatchMode))
            {
                return(false);
            }
            // check if there any out params
            if (updateSet.InsertsIdentity && !_driver.Supports(DbFeatures.OutParamsInBatchedUpdates))
            {
                return(false);
            }
            return(true);
        }
Example #4
0
 private void RefreshIdentityReferences(DbUpdateSet updateSet, IList <EntityRecord> records)
 {
     foreach (var rec in records)
     {
         if (rec.EntityInfo.Flags.IsSet(EntityFlags.ReferencesIdentity))
         {
             rec.RefreshIdentityReferences();
         }
     }
 }
Example #5
0
        public DbBatch Build(DbUpdateSet updateSet)
        {
            _batch = new DbBatch()
            {
                UpdateSet = updateSet
            };
            _commandBuilder = new DataCommandBuilder(_driver, batchMode: true, mode: SqlGenMode.PreferLiteral);

            AddScheduledCommands(updateSet.Session.ScheduledCommandsAtStart);
            foreach (var group in updateSet.UpdateGroups)
            {
                foreach (var tableGroup in group.TableGroups)
                {
                    AddUpdateGroup(tableGroup);
                }// foreach group
            }
            AddScheduledCommands(updateSet.Session.ScheduledCommandsAtEnd);
            FinalizeCurrentCommand(completed: true);
            return(_batch);
        }
Example #6
0
 private void SaveTableGroupRecordsOneByOne(DbUpdateTableGroup tableGrp, DataConnection conn, DbUpdateSet updateSet)
 {
     foreach (var rec in tableGrp.Records)
     {
         if (updateSet.InsertsIdentity && rec.EntityInfo.Flags.IsSet(EntityFlags.ReferencesIdentity))
         {
             rec.RefreshIdentityReferences();
         }
         var cmdBuilder = new DataCommandBuilder(this._driver);
         var sql        = SqlFactory.GetCrudSqlForSingleRecord(tableGrp.Table, rec);
         cmdBuilder.AddRecordUpdate(sql, rec);
         var cmd = cmdBuilder.CreateCommand(conn, sql.ExecutionType, sql.ResultProcessor);
         ExecuteDataCommand(cmd);
     }
 }
Example #7
0
        private void SaveChangesNoBatch(DbUpdateSet updateSet)
        {
            var session   = updateSet.Session;
            var conn      = updateSet.Connection;
            var withTrans = conn.DbTransaction == null && updateSet.UseTransaction;

            try {
                LogComment(session, "-- SaveChanges starting, {0} records ------------", updateSet.Records.Count);
                var start = _timeService.ElapsedMilliseconds;
                if (withTrans)
                {
                    conn.BeginTransaction(commitOnSave: true);
                }
                //execute commands
                ExecuteScheduledCommands(conn, session, session.ScheduledCommandsAtStart);
                //Apply record updates
                foreach (var grp in updateSet.UpdateGroups)
                {
                    foreach (var tableGrp in grp.TableGroups)
                    {
                        switch (tableGrp.Operation)
                        {
                        case LinqOperation.Insert:
                            if (CanProcessMany(tableGrp))
                            {
                                var cmdBuilder = new DataCommandBuilder(this._driver, mode: SqlGenMode.PreferLiteral);
                                var sql        = SqlFactory.GetCrudInsertMany(tableGrp.Table, tableGrp.Records, cmdBuilder);
                                cmdBuilder.AddInsertMany(sql, tableGrp.Records);
                                var cmd = cmdBuilder.CreateCommand(conn, sql.ExecutionType, sql.ResultProcessor);
                                ExecuteDataCommand(cmd);
                            }
                            else
                            {
                                SaveTableGroupRecordsOneByOne(tableGrp, conn, updateSet);
                            }
                            break;

                        case LinqOperation.Update:
                            SaveTableGroupRecordsOneByOne(tableGrp, conn, updateSet);
                            break;

                        case LinqOperation.Delete:
                            if (CanProcessMany(tableGrp))
                            {
                                var cmdBuilder = new DataCommandBuilder(this._driver);
                                var sql        = SqlFactory.GetCrudDeleteMany(tableGrp.Table);
                                cmdBuilder.AddDeleteMany(sql, tableGrp.Records, new object[] { tableGrp.Records });
                                var cmd = cmdBuilder.CreateCommand(conn, DbExecutionType.NonQuery, sql.ResultProcessor);
                                ExecuteDataCommand(cmd);
                            }
                            else
                            {
                                SaveTableGroupRecordsOneByOne(tableGrp, conn, updateSet);
                            }
                            break;
                        }
                    } //foreach tableGrp
                }
                //Execute scheduled commands
                ExecuteScheduledCommands(conn, session, session.ScheduledCommandsAtEnd);
                if (conn.DbTransaction != null && conn.Flags.IsSet(DbConnectionFlags.CommitOnSave))
                {
                    conn.Commit();
                }
                var end = _timeService.ElapsedMilliseconds;
                LogComment(session, "-- SaveChanges completed. Records: {0}, Time: {1} ms. ------------",
                           updateSet.Records.Count, end - start);
                ReleaseConnection(conn);
            } catch {
                ReleaseConnection(conn, inError: true);
                throw;
            }
        }