Say I have the following code. What are your thoughts on questions 1-4 below?
I think it's way too long when I have to list out most of the fields. Is there any better way of doing this?
I build up the DB column name so it can be used later in my select and insert statement.
This is where and how I use the string I build up in Section 2. Does it look good or ugly?
Audit is required after inserting/update a new record, therefore I need to get the old and new value. There should be a better way to do this I guess, but I just have no idea how.
I'm open to any suggestion that can make this code block short and more readable.
Public Function InsertOrUpdateData(ByVal patient As Patient, ByVal sqlMode As SQLMode, ByVal affectedColumn As String, Optional ByVal updateString As String = "") As CreatePatientStatus
Using conn As New SqlConnection(_myConnectionString)
Dim cmd As New SqlCommand
cmd.Connection = conn
conn.Open()
Try
'SECTION 1
'first I populate all the param before perform any action
With cmd.Parameters
.AddWithValue("@PCNO", patient.PCNO)
.AddWithValue("@PName", patient.PName)
.AddWithValue("@NRICType", patient.NRICType)
.AddWithValue("@NRIC", patient.NRIC)
'Another 80+ fields
.AddWithValue("@Created_Date", Now)
.AddWithValue("@Created_By", patient.CreateOrEditBy)
.AddWithValue("@Edit_Date", Now)
.AddWithValue("@Edit_By", patient.CreateOrEditBy)
.AddWithValue("@FirstSeen", Now)
End With
'SECTION 2
'this is list out all the affected DB column (It's FIXED, and always be)
Dim sbAffectedDBFields As New StringBuilder
sbAffectedDBFields.Append("PCNO,PName,NRICType,NRIC,")
sbAffectedDBFields.Append("Anoter 80+ fields")
sbAffectedDBFields.Append("Created_Date,Created_By,Edit_Date,Edit_By,FirstSeen")
'oldValue and newValue to be used later part for audit
Dim oldValue As String = String.Empty
Dim newValue As String = String.Empty
Dim dtOldValue As New DataTable
Dim dtNewValue As New DataTable
Dim sqlDataAdapter As New SqlDataAdapter(cmd)
If sqlMode = sqlMode.INSERT Then
'insert patient
'SECTION 3
cmd.CommandText = String.Format("INSERT INTO myPatient({0}) VALUES ({1})", sbAffectedDBFields.ToString, sbAffectedDBFields.Replace(",", ",@").ToString)
cmd.ExecuteNonQuery()
ElseIf sqlMode = sqlMode.UPDATE Then
'get old value before update
cmd.CommandText = String.Format("SELECT {0} FROM myPatient WHERE PCNO=@PCNO", sbAffectedDBFields.ToString)
sqlDataAdapter.SelectCommand.Parameters.AddWithValue("@PCNO", patient.PCNO)
sqlDataAdapter.Fill(dtOldValue)
'dtOldValue will have only one row always
'SECTION 4
For Each dr As DataRow In dtOldValue.Rows
For Each dc As DataColumn In dtOldValue.Columns
oldValue &= dr(dc).ToString & ","
Next
Next
oldValue.Remove(oldValue.Length - 1, 1) 'to remove last ","
'update patient
'updateString variable in a format of (field1=@field1,field2=@field2,fieldN=@fieldN)
cmd.CommandText = String.Format("UPDATE myPatient SET {0} WHERE PCNO=@PCNO", updateString)
cmd.ExecuteNonQuery()
End If
'get new value after update
cmd.CommandText = String.Format("SELECT {0} FROM myPatient WHERE PCNO=@PCNO", sbAffectedDBFields.ToString)
sqlDataAdapter.SelectCommand.Parameters.AddWithValue("@PCNO", patient.PCNO)
sqlDataAdapter.Fill(dtNewValue)
'dtNewValue will have only one row always
For Each dr As DataRow In dtNewValue.Rows
For Each dc As DataColumn In dtNewValue.Columns
newValue &= dr(dc).ToString & ","
Next
Next
newValue.Remove(newValue.Length - 1, 1) 'to remove last ","
'param tableName,affectedColumn,oldvalue,newvalue
Audit("myPatient", sbAffectedDBFields.ToString, oldValue, newValue)
Return True
Catch ex As Exception
ErrorLog.Log(ex, ErrorLog.LogLevel.Message, MethodBase.GetCurrentMethod())
Return False
End Try
End Using
End Function