How to throw an exception in BLL when no data found in DAL - asp.net

I am trying to throw an exception in my BLL when there is no corresponding carID for the license plate number I've entered in a text box.
My DAL looks like this:
Public Class DALCar
Private dc As New cars_modelDataContext
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).Single
Return result
End Function
End Class
And this is my BLL:
Public Class BLLCar
Private DALcar As New DALCar
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
End Function
End Class
So when there is no carID with this specific license plate an exception is throwed in my DAL, but how can I throw this exception in my BLL instead of in my DAL?

Use FirstOrDefault instead of Single
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).FirstOrDefault
Return result
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
If carID = Nothing Then
Throw New Exception(String.Format("Can't find car id for chassisNo : {0}", chassisNo_input))
End If
End Function

Because you're using Enumerable.Single in your LINQ expression. It throws an exception if there is more than one element in the sequence or if the sequence is empty.
If you can assume the sequence will always contains 0 or 1 element then you can replace Single with FirstOrDefault (see later for more on this). It'll return the first element in the sequence or Nothing if sequence is empty.
In this case you can check for Nothing in your BLL and throw the appropriate exception there.
Like this in your DAL:
Public Class DALCar
Private dc As New cars_modelDataContext
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim result = (From car In dc.Cars
Where car.License_Plate = licensePlate_input
Select car.License_Plate).FirstOrDefault
Return result
End Function
End Class
And this in your BLL:
Public Class BLLCar
Private DALcar As New DALCar
Public Function getCarIdByLicenePlate(ByVal licensePlate_input As String) As String
Dim carID As String = DALcar.getCarIdByLicensePlate(chassisNo_input)
If carId = Nothing Then
Throw New ArgumentException("There is no match.")
End If
End Function
End Class
If your query may returns more than one element than you have to consider if this is an error or not. If it's allowed and you want to process (return) the first one then go on with FirstOrDefault. If it's an error then you should return an enumeration from your DAL and to check the number of items in your BLL (otherwise, using Single, you'll still throw inside DAL).

Related

difficulty serializing a collection in web api 2 using knockoutjs

I have a knockoutjs web page doing a post to a VB .net Web API. for some reason my collection always shows nothing on the controller.
on the web page in the post here is my data.
data: ko.toJSON({
ShpmntCntrlNbr: self.ShpmntCntrlNbr,
MstrBillNbr: self.MstrBillNbr,
accesorialChangesHaveBeenMade: self.accesorialChangesHaveBeenMade,
DB2ACTCollection: actCollection
}),
this shows in the console (chrome developer tools) like this.
{
"ShpmntCntrlNbr":"11019813",
"MstrBillNbr":" ",
"accesorialChangesHaveBeenMade":true,
"DB2ACTCollection":[
{"ShpmntCntrlNbr":"11019813"}
]
}
here is .net VB controller
Public Function Post(data As VMFreightReleaseSaveDB2ChangesInput) As IHttpActionResult
Return Ok()
End Function
unfortunately when I put a stop sign in here and inspect data. I get
DB2ACTCollection Nothing
MstrBillNbr " "
ShpmntCntrlNbr "1101983"
accesorialChangesHaveBeenMade True
no clue why my DBACTCollection is showing as nothing. any thoughts?
and here are the classes.
Public Class VMFreightReleaseSaveDB2ChangesInput
Public Property ShpmntCntrlNbr() As String
Get
Return m_ShpmntCntrlNbr
End Get
Set(value As String)
m_ShpmntCntrlNbr = value
End Set
End Property
Private m_ShpmntCntrlNbr As String
Public Property MstrBillNbr() As String
Get
Return m_MstrBillNbr
End Get
Set(value As String)
m_MstrBillNbr = value
End Set
End Property
Private m_MstrBillNbr As String
Public Property accesorialChangesHaveBeenMade() As Boolean
Get
Return m_accesorialChangesHaveBeenMade
End Get
Set(value As Boolean)
m_accesorialChangesHaveBeenMade = value
End Set
End Property
Private m_accesorialChangesHaveBeenMade
Public Property DB2ACTCollection() As List(Of DB2_ACT2)
Get
Return m_DB2ACTCollection
End Get
Set(value As List(Of DB2_ACT2))
value = m_DB2ACTCollection
End Set
End Property
Private m_DB2ACTCollection As List(Of DB2_ACT2)
and
Public Class DB2_ACT2
Public Property ShpmntCntrlNbr() As String
Get
Return m_ShpmntCntrlNbr
End Get
Set(value As String)
m_ShpmntCntrlNbr = value
End Set
End Property
Private m_ShpmntCntrlNbr As String
End Class
Just a note here is my solution so far, not real happy with it but it seems to be working. instead of data As VMFreightReleaseSaveDB2ChangesInput I have data as JToken. then I just loop through it although I am still at a loss why the native .net web api serializer is not doing this.
Dim inner As JArray = data("DB2ACTCollection")
Dim ACTCollection = New List(Of DB2_ACT)
For Each item As JObject In inner
Dim ACT As New DB2_ACT
ACT.ShpmntCntrlNbr = item("ShpmntCntrlNbr")
ACTCollection.Add(ACT)
Next
Based on the JSON and seeing as the models are POCOs try using auto properties with DB2ACTCollection as an array and see if that deserializes properly
Public Class DB2_ACT2
Public Property ShpmntCntrlNbr As String
End Class
Public Class VMFreightReleaseSaveDB2ChangesInput
Public Property ShpmntCntrlNbr As String
Public Property MstrBillNbr As String
Public Property accesorialChangesHaveBeenMade As Boolean
Public Property DB2ACTCollection As DB2_ACT2()
End Class

Convert a standard EF list to a nested JSON

I have a WEB Method in my ASPX page that retrieves a List from SQL DB using Entity Framework.
Using rep As New RBZPOSEntities
q = rep.getSalesByLocation(fDate, tDate).ToList
End Using
Thereafter i use javascriptserializer to convert this list into a JSON string
Dim jss As JavaScriptSerializer = New JavaScriptSerializer()
Dim json As String = jss.Serialize(q)
So the above works great and i can use AJAX on the client side to display the results successfully.
The problem i am having now is converting a Flat List into a Nested JSON string.
So consider a list like:
locationName as string
MonthName as string
totalAmount as string
Which needs to be converted into a JSON like this:
[{locationName:'Tokyo',totalAmount:[100,200,300,400]},
{locationName:'New York',totalAmount:[500,600,700,800]}]
So the totalAmount values in the above case correspond to totalAmounts for a Location for a specific month. E.g. Tokyo total amount in January is 100, in February is 200 and etc.
What i can do:
I can create a nested list and populate it with results from EF and then serialize to JSON.
What i am asking:
Is there any other cleaner way to do it.
Thank you
As Todd has already said you need to convert your flat list into a list of another intermediate type. Let's call your existing Type the "InputType" and the Type you want the "OutputType"
Public Class InputClass
Public locationName as String
Public MonthName as String
Public totalAmount as String
End Class
Public Class OutputClass
Public LocationName As String
Public TotalAmount As List(Of String)
Public Sub New(groupedInputClass As IGrouping(Of String, InputClass))
LocationName = groupedInputClass.Key
TotalAmount = groupedInputClass.Select(Function(x) x.totalAmount).ToList()
End Sub
End Class
Then all you need to do is transform a List of InputType into a List of OutputType which is really easy with LINQ.
Public Class MappingHelper
Public Function Map (inputList as List(Of InputClass)) As List(Of OutputClass)
Dim groupedByLocation = inputList.GroupBy(Function(k) k.LocationName)
Dim nestedLocations = groupedByLocation.Select(Function(x) new OutputClass(x)).ToList()
Return nestedLocations
End Function
End Class
If you use an intermediate type, it may be helpful. Something like:
class RbzposInfo {
public string Location {get;set;}
public List<MonthlyRevenue> Monthlies {get;set;}
}
class MonthlyRevenue {
public string Month {get;set;}
public int Revenue {get;set;}
}
var result = new List<RbzposInfo>();
foreach (var r in q) { // q from your code
var info = new RbzposInfo();
// TODO: put r values into info.
result.Add(info);
}
Dim json As String = jss.Serialize(result);
(PS, sorry I mixed .NET languages on you. My code is C#.)

VB.NET hide a property member

I am currently working on the return class. The problem is I want to show the certain member only when some of the condition meet. Below is my code. I only want to show ResponseMsg member when the ResponseCode is 99 otherwise it will be hidden.
Public Class LoginResponse
Public Property TerminalID As String
Public Property ReaderID As String
Public Property TransRef As String
Public Property TransDateTime As String
Public Property Timeout As Integer
Public Property ResponseCode As String
Public Property ResponseMsg As String
Public Property Cryptogram As String
End Class
You can't that I know of. But you can do something like this:
Public Property ResponseMsg
Get
If ResponseCode <> SomeCodeValue
Return _responseCode
Else
Return Nothing
End if
End Get
End Property
You might want to think about making a specialized class.
Let's say you have your basic LoginResponse
Public Class LoginResponse
Public Property TerminalID As String
Public Property ReaderID As String
Public Property TransRef As String
Public Property TransDateTime As String
Public Property Timeout As Integer
Public Property ResponseCode As String
' Note: no ResponseMsg here
Public Property Cryptogram As String
End Class
Then you'd have an extended response class inheriting your basic LoginResponse:
Public Class LoginResponseEx : Inherits LoginResponse
Public Property ResponseMsg As String
End Class
Then where ever you create those LoginResponse objects, you just create one of the apropriate.
Let's say you have a GetResponse() procedure like:
Public Function GetResponse() As LoginResponse
Dim result As LoginResponse = Nothing
Dim code As Integer = GetSomeCode()
' ... get the other properties
' Say you have a const or something with the appropriate code: SPECIAL_CODE
If code = SPECIAL_CODE Then
Dim msg As String = GetSomeMessage()
result = New LoginResponseEx(..., code, msg, ...) ' have a special Response
Else
result = New LoginResponse(..., code, ...) ' have a normal Response
End If
Return result
End Function
Finally when checking the response you just check whether you have a special value in ResponseCode and cast the object respectivly.
'...
Dim resp as LoginResponse = GetResponse()
If resp.ResponseCode = SPECIAL_CODE Then
Dim respx as LoginResponseEx = CType(resp, LoginResponseEx)
Console.WriteLine("ResponseMessage was: " & respx.ResponseMsg
Else
Console.WriteLine("No ResponseMessage")
End If
'...
This way you have your basic LoginResponse with the ResponseMsg hidden in the special class ResponseLoginEx
Note when you do this you should think about how you implement virtual classes. e.g. the fields might have to be declared as Protected instead of Private, though i'm sure you'll do fine.
This also works with Serializable classes, of course.

How to make a VB.Net Function parameter a strongly-typed property instead of just a String

Here is class I reference in this question:
Public Class Enums
Public Enum Subscription As Byte
Vendor = 1
FreeTrial = 2
Standard = 3
Enterprise = 4
End Enum
End Class
In a VB.NET class I have the following property:
Private _optionSelection1 As String 'added by StackOverflow EDIT
Public Property OptionSelection() As String
Get
Return If(IsNothing(_optionSelection1), String.Empty, _optionSelection1)
End Get
Set(ByVal value As String)
_optionSelection1 = value
End Set
End Property
The property gets set from a Request.Form variable as follows: 'added by StackOverflow EDIT
Me.OptionSelection = HttpContext.Current.Request.Form("option_selection1") 'added by StackOverflow EDIT
I use this value later in a function:
Dim choiceMade As Enums.Subscription = SubscriptionOptionSelected(Me.OptionSelection)
I'm thinking the function might be stronger if its parameter could be "stronger" than String:
Private Function SubscriptionOptionSelected(ByVal value As String) As Enums.Subscription
Select Case value
Case "S10"
Return Enums.Subscription.Standard
Case "ENT"
Return Enums.Subscription.Enterprise
End Select
End Function
I've tried writing the function like the following but the compiler immediately complains:
Private Function SubscriptionOptionSelected(ByVal value As OptionSelection) As Enums.Subscription
Is there a way to use the Property as a type passed to this little function ?
What you are asking is redundant. OptionSelection is a string and the function you are calling is taking a string as an input. By saying you want the type of the parameter to be the property you are saying you want a string to be a string.
Now if that string had certain business logic that needed to be applied to it to be a valid string, then you need to create a class that can contain that business logic:
Public Class OptionSelection
Private _OptionString As String
Private _validStrings As String() = New String() {"S10", "ENT"}
Public Sub New(Optional ByVal AnOption As String = "S10")
If _validStrings.Contains(AnOption) Then
_OptionString = AnOption
Else
Throw New Exception("Value must be in the list of acceptable strings")
End If
End Sub
Public Property OptionSelection() As String
Get
Return _OptionString
End Get
Set(ByVal value As String)
If _validStrings.Contains(value) Then
_OptionString = value
Else
Throw New Exception("Value must be in the list of acceptable strings")
End If
End Set
End Property
Public Shared Narrowing Operator CType(ByVal input As String) As OptionSelection
Return New OptionSelection(input)
End Operator
End Class
Then your property changes to:
Private _optionSelection1 As OptionSelection
Public Property OptionSelection() As OptionSelection
Get
Return _optionSelection1
End Get
Set(ByVal value As OptionSelection)
_optionSelection1 = value
End Set
End Property
Your assignment changes to:
Me.OptionSelection = CType(HttpContext.Current.Request.Form("option_selection1"),OptionSelection)
And your function is then:
Private Function SubscriptionOptionSelected(ByVal value As OptionSelection) As Enums.Subscription
Select Case value.OptionSelection
Case "S10"
Return Enums.Subscription.Standard
Case "ENT"
Return Enums.Subscription.Enterprise
End Select
End Function
What all this code does for you is allow you to enforce what kind of strings are being stored in the OptionSelection. You can extend the allowed strings by including them in the array _validStrings.
If your application where to try and assign a string that did not exist in the _validStrings array, then an exception would be generated. So you get a kind of Business logic type safety.
Define your property as Enums.Subscription instead of String. An alternative could be to use Enum.TryParse() to validate the input for SubscriptionOptionSelected and throw an exception if the parsing fails. Here's an example of the property as the enum, although if the sole purpose of SubscriptionOptionSelected is to parse a string to an enum value then it isn't really necessary anymore.
Private _optionSelection1 As Enums.Subscription
Public Property OptionSelection() As Enums.Subscription
Get
Return _optionSelection1
End Get
Set(ByVal value As String)
_optionSelection1 = value
End Set
End Property
Private Function SubscriptionOptionSelected(ByVal value As Enums.Subscription) As Enums.Subscription
...
End Function
Here's an example where you use Enum.TryParse instead...
Private Function SubscriptionOptionSelected(ByVal value As String) As Enums.Subscription
Dim retVal As Enums.Subscription
If Not System.Enum.TryParse(Of Enums.Subscription)(value, retVal) Then
' Deal with invalid value... throw Exception maybe?
End If
Return retVal
End Function
So in your code (based on your updates) you could change your property to an enum and do this:
Me.OptionSelection = Me.SubscriptionOptionSelected(HttpContext.Current.Request.Form("option_selection1"))
This assumes that the value of Form("option_selection1") will be either the string or numeric equivalent value of your Enum elements. If the form submission values don't match, then I'm afraid you are stuck doing things as they are.

Inherit a class to remove a property and change method logic

The following class is used in an ASP.NET application to read currencies from a database result set and add them up (e.g. show totals in US Dollars plus show totals in GB Pounds). It works in the following manner:
Read currency ID value
If currency ID exists already, increase the total for that currency
If currency ID does not exist, add it to the list with its value
Next
It works well using the CurrencyID property as the differentiator between each unique currency. However, it has now become apparent that IsoCurrencySymbol is also unique for each currency by default, and so CurrencyID is not actually needed.
So... I was wondering if it would be possible to inherit from this class and remove any reference to CurrencyID, therefore making the CompareTo method use IsoCurrencySymbol instead.
The trick is to leave the existing class as it is used extensively, but introduce a modified version without CurrencyID being needed. Is this possible to do please?
<Serializable()> _
Public Class CurrencyCounter
<Serializable()> _
Private Class CurrencyType
Implements IComparable
Public IsoCurrencySymbol As String
Public CurrencySymbol As String
Public CurrencyID As Int16
Public Amount As Decimal
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
If Not TypeOf (obj) Is CurrencyType Then
Throw New ArgumentException("Object is not a currency type")
Else
Dim c2 As CurrencyType = CType(obj, CurrencyType)
Return Me.CurrencyID.CompareTo(c2.CurrencyID)
End If
End Function
End Class
Private _Currencies As List(Of CurrencyType)
Public Sub New()
_Currencies = New List(Of CurrencyType)
End Sub
Private Sub AddStructToList(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
If IsoCurrencySymbol <> String.Empty AndAlso Amount > 0 Then
Dim s As New CurrencyType
s.CurrencyID = CurrencyID
s.IsoCurrencySymbol = IsoCurrencySymbol
s.CurrencySymbol = CurrencySymbol
s.Amount = Amount
_Currencies.Add(s)
End If
End Sub
Public Sub Add(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
Dim ct As CurrencyType = _Currencies.Find(Function(obj) obj.CurrencyID = CurrencyID)
If ct IsNot Nothing Then
ct.Amount += Amount
Else
AddStructToList(CurrencyID, IsoCurrencySymbol, CurrencySymbol, Amount)
End If
End Sub
Public Sub Clear()
_Currencies.Clear()
End Sub
Public Function Count() As Integer
Return _Currencies.Count
End Function
Public Function RenderTotals() As String
' ...
End Function
End Class
No, you cannot do that. The whole point of inheritance it to ensure that all derived classes, if nothing else, at least share the same public interface as their base class. If you are removing a property, then it doesn't share the same interface and is therefore incompatible and not a candidate for inheritance.
If you can't say that the derived class is a type of the base class, then you can't use inheritance. For instance, I can say that an automobile is a type of vehicle, therefore, if I had an automobile class, I could have it inherit from a vehicle class. I can't however say that an insect is a type of vehicle. Therefore, even if they share most things in common, I can't have an insect class inherit from a vehicle class.
The reason for this limitation is because inheritance allows you to treat an object as if it were the base type (via type casting). For instance:
Public Sub AddPassengerToVehicle(v As Vehicle)
v.Passengers.Add(New Passenger())
End Sub
' ...
Dim auto As New Automobile()
Dim bug As New Insect()
AddPassengerToVehicle(auto) ' Works because an automobile is a type vehicle (inherits from vehicle)
AddPassengerToVehicle(bug) ' Can't possibly work (nor should it)
So, if you are in a situation where you need to have a derived class that removes/hides one of the members of its base class, you are headed in the wrong direction. In a case like that, you would need to create a whole new class which just happens to have a very similar interface, but has no direct relationship with the first class, for instance:
Public Class Vehicle
Public Property Passengers As List(Of Passenger)
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Insect
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
If you want to share functionality, such as the logic in the SpeedIsTooFast method in the above example, then there are a couple different ways to do that. This first would be to make wrapper methods which simply make calls to the other class, for instance:
Public Class Insect
Private _vehicle As New Vehicle()
Public Property MaxSpeed() As Integer
Get
Return _vehicle.MaxSpeed
End Get
Set(value As Integer)
_vehicle.MaxSpeed = value
End Set
End Property
Public Function SpeedIsTooFast(speed) As Boolean
Return _vehicle.SpeedIsTooFast(speed)
End Function
End Class
If you do it this way, it would be best to have both classes implement the same common interface so that you can use them interchangeably when necessary, for instance:
Public Interface ISelfPoweredMovingThing
Property MaxSpeed As Integer
Function SpeedIsTooFast(speed As Integer) As Boolean
End Interface
Another option would be to break out the common functionality into a third class and then use that class as the base for the other two, for instance:
Public Class SelfPoweredMovingThing
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Vehicle
Inherits SelfPoweredMovingThing
Public Property Passengers As List(Of Passenger)
End Class
Public Class Insect
Inherits SelfPoweredMovingThing
' Anything else specific only to insects...
End Class

Resources