Log an application error¶
Callers record an application error by calling one of the two CreateNewAppError factory overloads on clsAppError — one that accepts a framework ErrorInfoStruct and one that accepts discrete field values. Both overloads populate the same set of fields on a new clsAppError instance and immediately call Save(), so both converge on the identical insert-and-identity-retrieval lifecycle.
| Field | Value |
|---|---|
| Operation ID | OP-LV-01 |
| Trigger | Caller calls clsAppError.CreateNewAppError(inDPI, inErrorStruct) or clsAppError.CreateNewAppError(inDPI, inAppName, inEnvironment, inErrorDate, inErrorInfo, inErrorSource, inMachineName, inPageName, inStateInfo, inUserName) |
| Inputs | IDataPortalInfo; either a SAIF.Framework.Logging.ErrorInfoStruct or the nine discrete fields (AppName, Environment, ErrorDate, ErrorInfo, ErrorSource, MachineName, PageName, StateInfo, UserName) |
| Outputs | Saved clsAppError instance with AppErrorSeqNum populated; an InsertError business-object message if the insert did not affect exactly one row |
| Primary components | clsAppError.CreateNewAppError (both overloads), clsAppError.BeforeInsert, clsAppError.AfterInsert |
| Entry point | Application\SAIF.Application.LogView\clsAppError.vb |
Steps¶
- Allocate a new object. Both
CreateNewAppErroroverloads build aclsAppError.Criteriafrom the suppliedIDataPortalInfoand callinDPI.DataAccessLayer.CreateObject(Crit), which runs the BOFCreate()lifecycle method.Create()seeds all fields to empty strings and setsErrorDatetoNowbefore the factory overwrites them. - Populate fields from the caller's input.
- Struct overload: copies
ApplicationName,Environment,ErrorDate,ExceptionInfo,ExceptionSource,MachineName,PageName,StateInfo, andUsernamefrom theErrorInfoStructonto the correspondingclsAppErrorproperties. - Discrete-parameter overload: copies the nine caller-supplied arguments directly onto the same set of properties.
- Each property setter calls
MarkDirty()when the incoming value differs from the current value, which is what makes the object savable. - Save the object. Both overloads call
temp.Save()immediately after populating fields, entering the BOF save lifecycle for a new (dirty, not-yet-persisted) object, which routes toBeforeInsert/AfterInsertrather than update. - Build the insert request (
BeforeInsert). ANonQuerydata request is configured withMyCriteria.InsertSQL(SQL-003, App_Error) and bound parameters@App_Name,@Error_Date(or aDbType.DateTimenull placeholder whenErrorDateisDate.MinValue),@Environment,@Machine_Name,@Page_Name,@Error_Source,@State_Info,@Error_Info, and@User_Name. - A second scalar data request is queued in the same call with
SQLStatement = "Select @@IDENTITY"(SQL-001) to retrieve the generated sequence number in the same round trip. - Evaluate the insert result (
AfterInsert). The rows-affected value from the first data request is read. - If
RowsAffected <> 1: add theInsertErrorbusiness-object message (BR-006) and leaveAppErrorSeqNumunset — the object is not marked old, so it still reports as new/dirty. - Otherwise: read the
@@IDENTITYscalar result from the second data request, cast it toInteger, assign it tom_AppErrorSeqNum, and callMarkOld()to mark the object as persisted and clean. - Return the saved object. Both factory overloads return the same
tempreference used throughout, now populated withAppErrorSeqNumon success.
Process flow¶
The following diagram visualizes the two-overload create-and-save flow.
flowchart TD
Start([Caller calls CreateNewAppError]) --> Which{Struct or discrete<br>parameter overload?}
Which -->|Struct| MapStruct[Map ErrorInfoStruct fields<br>to clsAppError properties]
Which -->|Discrete| MapDiscrete[Map discrete arguments<br>to clsAppError properties]
MapStruct --> Save[Call Save]
MapDiscrete --> Save
Save --> Insert[BeforeInsert: build InsertSQL<br>and @@IDENTITY requests]
Insert --> Exec[Execute insert and<br>identity scalar request]
Exec --> Rows{RowsAffected = 1?}
Rows -->|No| Err([AddErrorMessage InsertError;<br>AppErrorSeqNum unset])
Rows -->|Yes| Identity[Read @@IDENTITY,<br>set AppErrorSeqNum, MarkOld]
Identity --> Done([Saved clsAppError returned])
Failure and edge-case behavior¶
- If
ErrorDateis left atDate.MinValue(never assigned),BeforeInsertbinds@Error_Dateas an explicitDbType.DateTimenull rather than a value, so the row is inserted with a null error date. - A
RowsAffectedvalue other than1— including0or more than1— is treated uniformly as an insert failure;AppErrorSeqNumremains unset and the object is not marked old, so a subsequentSave()would attempt the insert again. AfterInsertdoes not validateIsValidbefore proceeding, andAddBusinessRules()onclsAppErrorregisters no rules, so no field-level validation blocks the insert.*
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Sources¶
Application\SAIF.Application.LogView\clsAppError.vb