Lazy .NET. How to use it with list of objects? - asp.net

I have a webservice that implements a lazy handler that handles queries on db and fills list of structure. This is made to avoid to read from DB.
Basically I have:
Public Class Lazy_Handler
Implements IDisposable
Private lToRet As New List(Of External_Widget)
'[... other lists to be read from DB the first time]
Private Shared ReadOnly lazy As Lazy(Of Lazy_Handler) = _
New Lazy(Of Lazy_Handler)(Function() New Lazy_Handler())
Public Shared ReadOnly Property Instance As Lazy_Handler
Get
Return lazy.Value
End Get
End Property
Public Function list_of_external_widget() As List(Of External_Widget)
Try
If lToRet Is Nothing Then
lToRet = New List(Of External_Widget)
End If
If lToRet.Count > 0 Then
Return lToRet
End If
lToRet = New List(Of External_Widget)
'... QUERY FROM DB HERE, DETAILS OMITTED
Return lToRet
Catch ex As Exception
Purge("link_of_external_widget:" & ex.Message)
Return New List(Of External_Widget)
Finally
DBOperazioni.CloseConn()
End Try
End Function
End Class
so from my website I call something like
Dim list_of_external_widget As List(Of Lazy_Handler.External_Widget) = _
Lazy_Handler.Instance.list_of_external_widget()
I expect that the first time the lazy is created, then the query is executed. After that, no more lazy creations and no more queries on DB.
I'm right?
It works well, but sometimes (I don't know where) there something that becomes Nothing and I get error. What could it be?
Thank you

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

How to throw an exception in BLL when no data found in DAL

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).

class modules in asp.net file system website

I have a class module in my App_code folder.
Private _connection As MySqlConnection
Private _connStr As String
Public Function Connect(dbName As String) As Boolean
Try
_connStr = "Database=" & dbName & ";" & _
"Data Source=192.16.0.1;" & _
"User Id=user;Password=pass"
_connection = New MySqlConnection(_connStr)
_connection.Open()
_connection.Close()
Return True
Catch ex As Exception
_connection = Nothing
Return False
End Try
Return False
End Function
I usually program in webform apps. Why can't I access this function from my aspx code behind pages? I added the import statement for the class. If i make that function shared I cant have those private variables.
I call the function in my aspx lik so;
If Connect(dbName) then....
That gets me an error "non shared member requires an object reference"
You need to add the keyword "Shared" to the method signature, like so:
Private Shared _connection As MySqlConnection
Private Shared _connStr As String
Public Shared Function Connect(dbName As String) As Boolean
This is because otherwise you have instance class members, not static members. The compiler error message is quite self-explanatory.
if you look at this example works:
Public Shared Function example123(ByVal USER As Integer, ByVal Section As String, ByVal ACTION As String) As Boolean
you assign a function shared so you can see it from outside the class
I hope you work

VB.NET: Use Class Name as Expression

I'm not sure if this is possible but I would like to associate a class name reference to a shared member method / property / variable. Consider:
Public Class UserParameters
Public Shared Reference As Object
Public Shared Function GetReference() As Object
Return Reference
End Function
End Class
In another part of the program I would like to simply call UserParameters and have it return Reference either by aliasing GetReference or the variable directly.
I am trying to emulate the Application, Request, or Session variable:
Session(0) = Session.Item(0)
Any suggestions would be greatly appreciated.
You can't return an instance member from a static method directly (the static method can't access instance members because it isn't instantiated with the rest of the class, only one copy of a static method exists).
If you need to setup a class in such a way that you can return an instance from a static method you would need to do something similar to the following:
Public Class SampleClass
Private Sub New()
'Do something here
End Sub
Public Shared Function GetSample() As SampleClass
Dim SampleClass As SampleClass
SampleClass = New SampleClass
SampleClass.Sample = "Test"
Return SampleClass
End Function
Private _SampleString As String
Public Property Sample As String
Get
Return _SampleString
End Get
Private Set(ByVal value As String)
_SampleString = value
End Set
End Property
End Class
Public Class SampleClass2
Public Sub New()
'Here you can access the sample class in the manner you expect
Dim Sample As SampleClass = SampleClass.GetSample
'This would output "Test"
Debug.Fail(Sample.Sample)
End Sub
End Class
This method is used in various places in the CLR. Such as the System.Net.WebRequest class. where it is instantiated in this manner in usage:
' Create a request for the URL.
Dim request As WebRequest = WebRequest.Create("http://www.contoso.com/default.html")

VB.Net Initialising a class using System.Reflection and System.Type to create a session based singleton extension method

I have had several occasions recently to access a specific class several times over a relatively small time frame.
So I've been storing the value of the class in Session and trying to access it on page load, if it's not available creating a new instance and storing that in session.
So instead of constantly replicating the same code for different classes on different pages I'm trying to create an extension method to do this for me.
I want to use it like this
Dim objName as MyClass
objName.SessionSingleton()
So far this is what I have for my extension method:
<Extension()> _
Public Sub SessionSingleton(ByRef ClassObject As Object)
Dim objType As Type = ClassObject.GetType
Dim sessionName As String = objType.FullName
If TypeOf HttpContext.Current.Session(sessionName) Is objType And HttpContext.Current.Session(sessionName) <> "" Then
ClassObject = HttpContext.Current.Session(sessionName)
Else
Dim singleton As Object = New objType???????
HttpContext.Current.Session(sessionName) = singleton
ClassObject = singleton
End If
End Sub
I'm stuck on what to do when I make my new instance of my class (it would have to have a New() sub)
I'm not sure where to go from here... or even if this is the best way to do it.
I figured it out and am posting my code for reference. While digging thru pages about Class/Object Factories (thanks RBarry) I found several references to Activator.CreateInstance() in the System.Reflection Class I came up with this.
Imports Microsoft.VisualBasic
Imports System.Runtime.CompilerServices
Imports System.Reflection
Public Module enviornmentUtilities
<Extension()> _
Public Function SessionSinglton(ByVal objType As Type) As Object
Dim sessionName As String = objType.FullName.ToString
If Not HttpContext.Current.Session(sessionName) Is Nothing Then
HttpContext.Current.Trace.Write(HttpContext.Current.Session(sessionName).ToString)
Return HttpContext.Current.Session(sessionName)
Else
Dim ss = Activator.CreateInstance(objType)
HttpContext.Current.Session(sessionName) = ss
Return ss
End If
End Function
End Module
This will let you create a session based singleton from any class that does not require parameters in the new method (which isn't required for this to work)
To test I made a simple Class:
Public Class HasNew
Public FreshInstance As Boolean = True
Public Sub New()
HttpContext.Current.Trace.Warn("This Class has a new method")
End Sub
Public Sub CheckFreshness()
If FreshInstance Then
HttpContext.Current.Trace.Warn("Fresh HasNew Instance")
FreshInstance = False
Else
HttpContext.Current.Trace.Warn("NotFresh HasNew Instance")
End If
End Sub
Public Shared Function type() As Type
Return GetType(HasNew)
End Function
Public Shared Function SessionSinglton() As HasNew
Return GetType(HasNew).SessionSinglton
End Function
End Class
You'll notice the two Public Shared Methods type() and SessionSinglton which calls the above extension method.
With those two functions added we have three ways to initiate the Session Singlton demonstrated here:
Dim HN As HasNew
HN = HasNew.SessionSinglton
HN.CheckFreshness()
HN = HasNew.type.SessionSinglton
HN.CheckFreshness()
HN = GetType(HasNew).SessionSinglton
HN.CheckFreshness()
The Trace Output for this file is as follows:
This Class has a new method
Fresh HasNew Instance
NotFresh HasNew Instance
NotFresh HasNew Instance
The classes new() method is accessed on the first call to the SessionSinglton method and subsequent calls reflect that the instance is in fact being pulled from memory.
I hope this helps someone else in the future.
If you used generics you could just do New T(). Also your SessionSingleton returns "object" type, requiring casting. I did not test this but it should work.
Imports Microsoft.VisualBasic
Imports System.Runtime.CompilerServices
Imports System.Reflection
Public Module enviornmentUtilities
<Extension()> _
Public Function SessionSinglton(Of T As {Class, New})(ByVal obj As T) As T
Dim sessionName As String = obj.GetType.Name
If Not HttpContext.Current.Session(sessionName) Is Nothing Then
HttpContext.Current.Trace.Write(HttpContext.Current.Session(sessionName).ToString)
Return HttpContext.Current.Session(sessionName)
Else
Dim ss = New T()
HttpContext.Current.Session(sessionName) = ss
Return ss
End If
End Function
End Module

Resources