/// <summary> /// Check whether the entity was modified in the database since it was loaded. /// </summary> /// <remarks> /// Refer to the Developer's Guide about the optimistic concurrency model. /// The <see cref="Context" /> property must have a value of a valid object context with open database connection. /// </remarks> /// <exception cref="InvalidConcurrencyVersionException">Thrown when a potential concurrency issue is detected.</exception> /// <exception cref="LockingCollisionException">TODO</exception> protected void CheckConcurrency() { // TODO: implement locking for move operations (don't allow move if any locked) string sql = "spCheckEntityConcurrency"; using (SqlCommand cmd = Context.CreateStoredProcedureCommand(sql)) { AppendBasicParameters(cmd); cmd.Parameters.Add("@LockOwner", SqlDbType.UniqueIdentifier).Value = Context.JobGuid; cmd.Parameters.Add("@ConcurrencyVersion", SqlDbType.Binary, 8).Value = BitConverter.GetBytes(this.concurrencyVersion); cmd.Parameters.Add("RETVAL", SqlDbType.Int).Direction = ParameterDirection.ReturnValue; cmd.ExecuteNonQuery(); int retval = (int)cmd.Parameters["RETVAL"].Value; if (retval < 0) { Jhu.Graywulf.Logging.Event e = new Jhu.Graywulf.Logging.Event("Jhu.Graywulf.Registry.Entity.CheckConcurrency", this.guid);; switch (retval) { case -1: e.Message = LogMessages.InvalidConcurrencyVersion; Context.LogEvent(e); throw new InvalidConcurrencyVersionException(); case -2: e.Message = LogMessages.LockingCollision; Context.LogEvent(e); throw new LockingCollisionException(); } } } }
/// <summary> /// Saves the entity to the database. /// </summary> /// <remarks> /// This function attempts to save the entity but throws and exception if /// the value of the <b>forceOverwrite</b> parameter is false and a concurrency issue is detected. /// The <see cref="Context" /> property must have a value of a valid object context with open database connection. /// </remarks> /// <param name="forceOverwrite">Determines if concurrency issues are ignored.</param> /// <exception cref="InvalidConcurrencyVersionException"> /// Thrown when someone else modified the entity since it was loaded from the database. /// </exception> public void Save(bool forceOverwrite) { // Check entity duplicate var ef = new EntityFactory(Context); if (ef.CheckEntityDuplicate(this.EntityType, this.Guid, this.parentReference.Guid, this.name)) { Jhu.Graywulf.Logging.Event e = new Jhu.Graywulf.Logging.Event("Jhu.Graywulf.Registry.Entity.CheckConcurrency", this.guid);; e.Message = String.Format(LogMessages.DuplicateName, name); throw new DuplicateNameException(); } if (!IsExisting) { Create(); } else { Modify(forceOverwrite); } }
/// <summary> /// Sets a single job instance checkpoint's identified by its name. /// </summary> /// <param name="name">Name of the checkpoint.</param> /// <param name="executionStatus">Execution status of the checkpoint.</param> /// <remarks> /// This function is called by the <b>Jhu.Graywulf.Workflow.Activities.CheckpointActivity</b> /// to record the sequential provenance information of the executing job. /// </remarks> public void SetCheckpoint(string name, JobExecutionState executionStatus) { string sql = "spSetJobInstanceCheckpoint"; using (SqlCommand cmd = Context.CreateStoredProcedureCommand(sql)) { cmd.Parameters.Add("@UserGuid", SqlDbType.UniqueIdentifier).Value = Context.UserGuid; cmd.Parameters.Add("@JobInstanceGuid", SqlDbType.UniqueIdentifier).Value = Guid; cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 128).Value = name; cmd.Parameters.Add("@ExecutionStatus", SqlDbType.Int).Value = executionStatus; cmd.ExecuteNonQuery(); } // Write log entry Jhu.Graywulf.Logging.Event e = new Jhu.Graywulf.Logging.Event("Jhu.Graywulf.Registry.JobInstance.SetCheckpoint", this.Guid); e.UserData.Add("Name", name); e.UserData.Add("ExecutionStatus", executionStatus.ToString()); Context.LogEvent(e); }