/// <summary>
 /// Initializes a new instance of the JobRecord class.
 /// </summary>
 /// <param name="record">The prototype <see cref="JobRecord"/> to initialize this instance from.</param>
 public JobRecord(JobRecord record)
     : this()
 {
     if (record != null)
     {
         record.CopyProperties(this);
     }
 }
        /// <summary>
        /// Performs the concrete finishing of the given job run.
        /// </summary>
        /// <param name="run">A job run to finish.</param>
        /// <param name="record">The run's related record.</param>
        /// <param name="trans">The transaction to access the job store in.</param>
        private void FinishJobRun(JobRun run, JobRecord record, IJobStoreTransaction trans)
        {
            record.FinishDate = run.FinishDate;

            if (run.ExecutionException != null)
            {
                record.Exception = new ExceptionXElement(run.ExecutionException).ToString();
                record.Status = JobStatus.Failed;

                this.RaiseEvent(this.Error, new JobErrorEventArgs(record, run.ExecutionException));
                this.EnqueueJobForRetry(run.Job, trans);
            }
            else if (run.WasRecovered)
            {
                record.Status = JobStatus.Interrupted;
            }
            else
            {
                record.Status = JobStatus.Succeeded;
            }

            if (this.DeleteRecordsOnSuccess)
            {
                this.store.DeleteJob(record.Id.Value, trans);
            }
            else
            {
                this.store.SaveJob(record, trans);
            }

            this.runs.Remove(record.Id.Value);
            this.RaiseEvent(this.FinishJob, new JobRecordEventArgs(record));
        }
        /// <summary>
        /// Creates an insert or update command.
        /// </summary>
        /// <param name="connection">The connection to create the command with.</param>
        /// <param name="record">The record to insert or update.</param>
        /// <returns>An insert or update command.</returns>
        protected virtual DbCommand CreateSaveCommand(DbConnection connection, JobRecord record)
        {
            DbCommand command = connection.CreateCommand();
            command.CommandType = CommandType.Text;

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            bool creating = !record.Id.HasValue;

            if (creating)
            {
                sb1.AppendFormat(CultureInfo.InvariantCulture, "INSERT INTO {0}(", this.TableName);
                sb2.Append(" VALUES(");
            }
            else
            {
                sb1.AppendFormat(CultureInfo.InvariantCulture, "UPDATE {0} SET ", this.TableName);
            }

            for (int i = 0; i < readJobRecordProperties.Length; i++)
            {
                string name = readJobRecordProperties[i].Name;
                object value = readJobRecordProperties[i].GetValue(record, null);

                if (i > 0)
                {
                    sb1.Append(",");

                    if (creating)
                    {
                        sb2.Append(",");
                    }
                }

                if (creating)
                {
                    sb1.Append(this.ColumnName(name));
                    sb2.Append(this.ParameterName(name));
                }
                else
                {
                    sb1.AppendFormat(CultureInfo.InvariantCulture, "{0} = {1}", this.ColumnName(name), this.ParameterName(name));
                }

                if (value != null && value.GetType().IsEnum)
                {
                    value = value.ToString();
                }

                command.Parameters.Add(this.ParameterWithValue(this.ParameterName(name), value));
            }

            if (creating)
            {
                sb1.Append(")");
                sb2.AppendFormat(CultureInfo.InvariantCulture, "); {0}", this.SelectLastInsertIdSql);
            }
            else
            {
                sb1.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0} = {1};", this.ColumnName("Id"), this.ParameterName("Id"));
                command.Parameters.Add(this.ParameterWithValue(this.ParameterName("Id"), record.Id.Value));
            }

            command.CommandText = String.Concat(sb1, sb2);
            return command;
        }
 /// <summary>
 /// Initializes a new instance of the JobErrorEventArgs class.
 /// </summary>
 /// <param name="record">The <see cref="JobRecord"/> the event is being raised for.</param>
 /// <param name="ex">The <see cref="Exception"/> that caused the error.</param>
 public JobErrorEventArgs(JobRecord record, Exception ex)
     : base(record)
 {
     this.Exception = ex;
 }
        /// <summary>
        /// Creates a new <see cref="JobRecord"/> instance from the data at the current position
        /// of the given reader.
        /// </summary>
        /// <param name="reader">The reader to create the record from.</param>
        /// <returns>The created record.</returns>
        protected virtual JobRecord CreateRecord(DbDataReader reader)
        {
            JobRecord record = new JobRecord();
            int fieldCount = reader.FieldCount;

            while (fieldCount > 0)
            {
                int ordinal = fieldCount - 1;
                string fieldName = reader.GetName(ordinal);
                string propertyName = this.PropertyName(fieldName);
                PropertyInfo info = writeJobRecordProperties.Where(p => p.Name.Equals(propertyName, StringComparison.Ordinal)).FirstOrDefault();

                if (info != null)
                {
                    if (!reader.IsDBNull(ordinal))
                    {
                        object value = reader[ordinal];

                        if (typeof(DateTime?).IsAssignableFrom(info.PropertyType))
                        {
                            info.SetValue(record, new DateTime(Convert.ToDateTime(value, CultureInfo.InvariantCulture).Ticks, DateTimeKind.Utc), null);
                        }
                        else if (typeof(JobStatus?).IsAssignableFrom(info.PropertyType))
                        {
                            info.SetValue(record, Enum.Parse(typeof(JobStatus), Convert.ToString(value, CultureInfo.InvariantCulture)), null);
                        }
                        else if (typeof(int?).IsAssignableFrom(info.PropertyType))
                        {
                            info.SetValue(record, Convert.ToInt32(value, CultureInfo.InvariantCulture), null);
                        }
                        else if (typeof(string).IsAssignableFrom(info.PropertyType))
                        {
                            info.SetValue(record, Convert.ToString(value, CultureInfo.InvariantCulture), null);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }

                --fieldCount;
            }

            return record;
        }
        /// <summary>
        /// Saves the given job record, either creating it or updating it.
        /// </summary>
        /// <param name="record">The job to save.</param>
        /// <param name="transaction">The transaction to execute the command in.</param>
        public override void SaveJob(JobRecord record, IJobStoreTransaction transaction)
        {
            SqlJobStoreTransaction trans = transaction as SqlJobStoreTransaction;
            DbConnection connection = null;
            DbCommand command = null;
            bool creating = !record.Id.HasValue;

            try
            {
                if (trans != null)
                {
                    command = this.CreateSaveCommand(trans.Connection, record);
                    command.Transaction = trans.Transaction;
                }
                else
                {
                    connection = this.CreateAndOpenConnection();
                    command = this.CreateSaveCommand(connection, record);
                }

                if (creating)
                {
                    using (DbDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            record.Id = Convert.ToInt32(reader[0], CultureInfo.InvariantCulture);
                        }
                    }
                }
                else
                {
                    command.ExecuteNonQuery();
                }
            }
            finally
            {
                if (command != null)
                {
                    command.Dispose();
                }

                this.DisposeConnection(connection);
            }
        }
 /// <summary>
 /// Saves the given job record, either creating it or updating it.
 /// </summary>
 /// <param name="record">The job to save.</param>
 /// <param name="transaction">The transaction to execute the command in.</param>
 public abstract void SaveJob(JobRecord record, IJobStoreTransaction transaction);
 /// <summary>
 /// Saves the given job record, either creating it or updating it.
 /// </summary>
 /// <param name="record">The job to save.</param>
 public virtual void SaveJob(JobRecord record)
 {
     this.SaveJob(record, null);
 }
 /// <summary>
 /// Initializes a new instance of the JobRecordEventArgs class.
 /// </summary>
 /// <param name="record">The <see cref="JobRecord"/> the event is being raised for.</param>
 public JobRecordEventArgs(JobRecord record)
 {
     this.Record = new JobRecord(record);
 }