.NET Framework - How best pass errors from SQL to business, user tiers?
Asked By Ronald S. Cook
26-Jun-07 12:03 PM
How would you recommend passing errors back from your proc to your business
tier to the client (assuming you have full control of all layers)?
Take InsertUser for instance. The proc will automatically raise an error if
someone tries to create a user name for themselves that is already taken.
I could relay that error to the client but the message is not so user
friendly.
I could do a SELECT in my proc to see if the user name is already in use and
could then send back @@ERROR = 99 or some other value. But then that would
require my two layers "getting together" on what each value will mean.
Should I instead be sending back more user friendly error strings from the
proc that are then passed back to the client?
What is a best practice that you would recommend?
Thanks,
Ron
MessageArchive.LookupMessage
(1)
ErrorDescription
(1)
String.Empty
(1)
Database
(1)
Lookup
(1)
TsqlErrorNumber
(1)
MessageArchive
(1)
LookupMessage
(1)
sloan replied...

Do you have a unique constraint on your database column?
Or are you adding code to do the check (instead of the constraint)?
A ~~~~long time ago, I wrote something like this (below).
Where certain numbered TSQL numbers were matched to a description.
This was way back when the EMAB (exception management application block) was
recent technology.
Public Class TsqlBaseException : Inherits
Microsoft.ApplicationBlocks.ExceptionManagement.BaseApplicationException
Private m_errorNumber As Int32
Private m_errorDescription As String
Public Sub New(ByVal tsqlErrorNumber As Int32)
MyBase.New((MessageArchive.LookupMessage(tsqlErrorNumber)),
Nothing)
Me.m_errorNumber = tsqlErrorNumber
Me.m_errorDescription =
MessageArchive.LookupMessage(ErrorNumber)
End Sub
Public ReadOnly Property ErrorNumber() As Int32
Get
Return Me.m_errorNumber
End Get
End Property
Public ReadOnly Property ErrorDescription() As String
Get
Return Me.m_errorDescription
End Get
End Property
End Class
Public Class MessageArchive
Public Const DBERROR_SUCCESS As Integer = 0
'' Use 50000-59999 for "generic errors"
Public Const DBERROR_FAILURE As Integer = 50000 ' used for general
failure
Public Const DBERROR_CONCURRENCY_FAILURE As Integer = 50001
Public Const DBERROR_ITEM_EXISTS As Integer = 50002
Public Const DBERROR_NO_DATA_FOUND As Integer = 50003
'' Use 60001-69999 for "app specific errors"
Public Const DBERROR_TITLENAME_DOESNOTEXIST As Integer = 60001 ' used
for specific failure
Public Const DBERROR_TITLENAME_EXISTS_BUTNOT_TITLEID As Integer = 60002
' used for specific failure
Private Sub New()
End Sub
Public Shared Function LookupMessage(ByVal errorNumber As Integer) As
String
Dim returnValue As String = String.Empty
Select Case errorNumber
Case DBERROR_SUCCESS
returnValue = "The procedure was sucessful"
Case DBERROR_FAILURE
returnValue = "The procedure failed"
Case DBERROR_CONCURRENCY_FAILURE 'This was the timestamp one
returnValue = "The procedure failed due to a concurrency
issue"
Case DBERROR_ITEM_EXISTS
returnValue = "The procedure failed because the data item
with the necessary unique value already exists"
Case DBERROR_NO_DATA_FOUND
returnValue = "The procedure failed because no data was
found matching the input criteria"
''' App Specific Below this Line (>60000)
Case DBERROR_TITLENAME_DOESNOTEXIST
returnValue = "A title with that value does not exist"
Case DBERROR_TITLENAME_EXISTS_BUTNOT_TITLEID
returnValue = "A title with that value exists, but the
titleId is invalid"
Case Else
returnValue = "An Unknown Error has occurred. Return_Value
= '" + returnValue.ToString() + "' Please alert a developer that there is a
mismatch between the ErrorNumber and the Lookup Value"
End Select
Return returnValue
End Function
End Class
Peter Bradley replied...
Ysgrifennodd Ronald S. Cook:
We use custom exceptions. That is, we throw an exception of an
appropriate type, with an appropriate message.
Our exceptions are defined in their own libraries, which we reference
wherever they are needed. Needless to say all our custom exceptions
share a namespace.
Peter

public string ad_VP { get; set; } public string ad_Auftragsnummer { get; set; } public string Field3 { get { arturn string.Empty; } } public string ad_Positionstyp { get; set; } public DateTime ad_Auftragsdatum { get; set; } public string ad_Kennzeichen { get; set; } public string ad_Kampagne { get; set; } public string Field8 { get { arturn string.Empty; } } public int ad_Uebermittelung { get; set; } public string kd_Nummer { get; set; } public string kd_Anarde { get; set public int kd_VorwahlTelefon1 { get; set; } public int kd_Telefon1 { get; set; } public string Field23 { get { arturn string.Empty; } } public string Field24 { get { arturn string.Empty; } } public string kd_Email1 { get; set; } public string Field26 { get { arturn string.Empty; } } public string kd_Geburtsdatum
ByVal row As Integer) _ As String Dim str As String If possible(col, row) = String.Empty Then str = "123456789" Else str = possible(col, row) End If Dim r, c As Integer means there is a actual value in it str = str.Replace(actual(col, r).ToString(), String.Empty) End If Next 'Step (2) check by row For c = 1 To 9 If actual means there is a actual value in it str = str.Replace(actual(c, row).ToString(), String.Empty) End If Next 'Step (3) check within the minigrid Dim startC, startR As Integer startC startC + 2 If actual(cc, rr) <> 0 Then str = str.Replace(actual(cc, rr).ToString(), String.Empty) End If Next Next 'if possible value is string.Empty, then error If str = String
string.Empty .NET Framework I have been told that it is a good idea to *always* declare string variables with a default value of string.Empty - for cases where an initial value is not known. . . like this: string myString = string.Empty; / / do this string myString; / / do not do this Questions 1. Is that a good rule initializing string variables with null is in appropriate in a variety of situations. Initializing with string.Empty (or the equivalent) is desirable when you want to always be able to assume the
const int MaxBuzzFrequency = 10000; const int MaxDiveDepth = 4000; const int MaxLength = 800; private string chosenFileName = string.Empty; private FoodManager foodManager = new FoodManager(); private AnimalManager animalManager = new AnimalManager(); private int[] categoryInfo = new int specific initialize / / / < / summary> private void InitializeGUI() { btnAddFood.Enabled = false; btnDeleteFood.Enabled = false; ClearExtraCategoryField(); txtName.Text = string.Empty; txtTeeth.Text = string.Empty; txtAge.Text = string.Empty; InitEaterType(); InitGenderType(); InitCategoryType(); InitAnimalType(); InitHousingType(); InitFoodItems(); selectedAnimal = null; } private void ClearExtraCategoryField() { txtTeeth.Text = string.Empty
string = "" or = string.Empty? .NET Framework string = "" or string = string.Empty? should is the proper way? Sami C# Discussions IsNullOrEmpty (1) DotNetReflector (1) Eq (1) OP (1) SoftCircuits (1) FxCop (1) TeX (1) Postscript (1) string str = 3D string.Empty is the proper and more efficient way. Thanks, Well, it's not more efficient as both string literals, but the code more closely resembles the intention. If you always use string.Empty when you want an empty string, you know that when you find "" in your code