VB.Net to optimize execution by keeping data other than fetching data from database everytime - vb.net

I am newbie in vb.net I am trying to optimize my code execution that i am working on . i am working on a program having more than 45 forms. In every form its calling the function IsPowerUser to check is power user
If we can store all details about user while logging in , then we need to use these values every time when we needed instead of collecting data from database . May be this question belongs to VB Basics.

You can use lazy initialization to postpone the database call until you actually need the information (if ever), and then store the value for re-use.
Private _isPowerUser As New Lazy(Of Boolean)(AddressOf GetIsPowerUser)
Public Function IsPowerUser() As Boolean
Return _isPowerUser.Value
End Function
Private Function GetIsPowerUser() As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
In this sample, _isPowerUser is a backing field that uses lazy initialization. It is first initialized when someone calls IsPowerUser. Under the covers, Lazy(Of T) then calls the delegate GetIsPowerUser() that does all the heavy lifting to retrieve the value from the database.
Lazy(Of T) only needs to call GetIsPowerUser() once.
In other words: any consecutive calls to IsPowerUser() do not trigger GetIsPowerUser().
EDIT (1/2)
Lazy(Of T) was not introduced until .NET 4, so here is a code sample that works for .NET 2 and above:
Private _isPowerUser As Boolean?
Private lazyLock As New Object
Public Function IsPowerUser() As Boolean
If Not _isPowerUser.HasValue Then
SyncLock lazyLock
If Not _isPowerUser.HasValue Then
_isPowerUser = GetIsPowerUser()
End If
End SyncLock
End If
Return _isPowerUser.Value
End Function
Private Function GetIsPowerUser() As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
EDIT (2/2)
I changed my code sample to work in a multi-user environment:
Private _powerUsers As New Dictionary(Of Long, Boolean)
Private ReadOnly LazyLock As New Object
Public Function IsPowerUser(userId As Long) As Boolean
If Not _powerUsers.ContainsKey(userId) Then
SyncLock LazyLock
If Not _powerUsers.ContainsKey(userId) Then
_powerUsers.Add(userId, GetIsPowerUser(userId))
End If
End SyncLock
End If
Return _powerUsers.Item(userId)
End Function
Private Function GetIsPowerUser(UId As Long) As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
Usage example:
Dim Steven As Long = 454151
If IsPowerUser(Steven) Then
Console.WriteLine("Steven is a power user.")
Else
Console.WriteLine("Steven is a normal user.")
End If

Related

VB.NET Simplify Action(Of T)

I am using VB.Net 4 and am successfully using a class with the following signature:
Sub Register(Of TMessage)(recipient As Object, action As
System.Action(Of TMessage))
I want to learn about lambdas in VB so I wanted to see if I can simplify my current code.
CURRENTLY: I have the following in the constructor of a class (simplified for clarity)
Public Sub New()
Dim myAction As New Action(Of String)(AddressOf HandleMessage)
Messenger.Default.Register(Of [String])(Me, myAction)
End Sub
And later in the class I have the following:
Private Function HandleMessage(sMsg As String)
If sMsg = "String Value" Then
If Me._Selection.HasChanges Or Me._Selection.HasErrors Then
Return True
End If
Return False
Else
Return False
End If
End Function
QUESTION: Is there a way to simplify this into a lambda like in C# where I don't have to declare the MyAction variable in the constructor, but just pass the string value to HandleMessage function "inline" with the register sub? (I hope that makes sense)
So your constructor code is equivalent to:
Messenger.[Default].Register(Of String)(Me,
Function(sMsg)
If sMsg = "String Value" Then
If Me._Selection.HasChanges Or Me._Selection.HasErrors Then
Return True
End If
Return False
Else
Return False
End If
End Function)
It's worth mentioning though you don't need to use lambdas just to get rid of your explicit delegate creation. This is perfectly legal too:
Messenger.[Default].Register(Of String)(Me, AddressOf HandleMessage)
There is a bit of strangeness though with your example: you've declared your Register method as taking an Action(Of TMessage) which means the function passed needs no return value. Your function however is returning a Boolean. Visual Basic here is doing the fancy "delegate relaxation" and is throwing away the return value. So all your Return True/Return False bits aren't actually doing anything special.

Trying to get asynchronous functions with arguments and returns to work

I have been trying to get a function to work asynchronously with a GUI window, and having very limited success.
The code below is my function, XXX, with a delegate and Callback - to allow stopping the GUI thread, without getting an error.
It works though - if it is a Sub, not a function, and if it doesn't have any arguments.
I don't know how to change it so I can check its return value... I have found a little help in some examples, http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncstate.aspx - but they print the return value in the callback, and I can't see how to get it in the caller.
I can't find any way to use arguments in my function.
Private Function XXX_Callback(ByVal ia As IAsyncResult)
Dim d As XXXDelegate = CType(CType(ia, Runtime.Remoting.Messaging.AsyncResult).AsyncDelegate, XXXDelegate)
d.EndInvoke(ia)
Dim result As AsyncResult = CType(ia, AsyncResult)
Dim caller As XXXDelegate = CType(result.AsyncDelegate, XXXDelegate)
Dim returnValue As Boolean = caller.EndInvoke(ia)
XXX_Finish() ' needs the "vvv argument, I don't know how to get it
' The returnValue is here but I don't know how to send it to the caller
End Function
'Private Function XXX_Finish(ByVal vvv as Boolean) As Boolean
' this probably needs to return something, I don't know what/ how to get it
Private Function XXX_Finish() As Boolean
' something
myGui.Finish()
End Function
' Private Delegate Function XXXDelegate(ByVal vvv As Integer) As Boolean
' Public Function XXX(ByVal vvv As Integer) As Boolean ' This is what I would like
Private Delegate Sub XXXDelegate()
Public Sub XXX()
'
myGui.Update()
'
End Sub
Public Sub Caller()
'
myGui = New SomeGui()
myGui.Begin()
Dim t As New XXXDelegate(AddressOf XXX)
t.BeginInvoke(AddressOf XXX_Callback, Nothing)
' more code, another call
End Sub
Private myGui As SomeGui
Please, could someone help me get this into a better shape, or get some examples that will help ? With the ones I have found in the past two days, I have reached a dead end...
Thank you.
After searching through lots of posts on the web, and reading a couple of books, I have found the best resource, with examples for each case that one might encounter:
http://support.microsoft.com/kb/315582
The answers to this particular question are in the above link, "Sample 2: Calling A Method Asynchronously by Using the EndInvoke() Call Pattern" and "Sample 5: Executing a Callback When an Asynchronous Method Completes."
The best thing about it though is the simple and organized fashion in which the options to use Invoke, EndInvoke, Callback are explained.
One thing to note: for my question above, the essential breakthrough was when I read the words "BeginInvoke() returns immediately and does not wait for the asynchronous call to complete."
So... trying to call another method, after it, was the wrong approach.
This is how i made an asyncronous function calls.
I declare the function in the module.
Private Delegate Function fnBolAsyncCallVerificacionNuevaVersion(ByVal pIntModo As Integer, ByVal pIntAccion As Integer) As Boolean
Private Delegate Function fnBolAsyncCallActualizacionTipoCambio(ByVal pIntActualizacionMandatoria As clsBusinessBoxData.tblTipoCambio.enumActualizacionMandatoria) As typBolResultadoFuncion
The functions receive some parameters and the first returns a boolean and the second returns an structure with 2 data, one boolean and one string.
In the load event of the form I call the functions.
sAsyncVerificaVersion = New fnBolAsyncCallVerificacionNuevaVersion(AddressOf fnBolVerificaActualizacion)
sAsyncVerificaVersion.BeginInvoke(enumDisplayGUIMode.Silent, typApplicationUpdate.CheckOnly, New AsyncCallback(AddressOf fnBolTerminaVerificacionVersion), Nothing)
sAsyncActualizaTiposCambio = New fnBolAsyncCallActualizacionTipoCambio(AddressOf fnBolActualizaTiposCambioYahoo)
sAsyncActualizaTiposCambio.BeginInvoke(clsBusinessBoxData.tblTipoCambio.enumActualizacionMandatoria.No, New AsyncCallback(AddressOf fnBolTerminaActualizacionTipoCambio), Nothing)
These calls will execute the function asyncronous and will callback the function defined when finished.
Then i receive the results in the callback functions defined.
Private Function fnBolTerminaVerificacionVersion(ByVal pIarResultado As IAsyncResult) As Boolean
Dim sClsResultado = CType(pIarResultado, Messaging.AsyncResult)
Dim sIarResultado As fnBolAsyncCallVerificacionNuevaVersion = CType(sClsResultado.AsyncDelegate, fnBolAsyncCallVerificacionNuevaVersion)
Dim sBolExisteNuevaVersion As Boolean = False
CheckForIllegalCrossThreadCalls = False
sBolExisteNuevaVersion = sIarResultado.EndInvoke(pIarResultado)
mnuBajarActualizacion.Enabled = sBolExisteNuevaVersion
CheckForIllegalCrossThreadCalls = True
Return True
End Function
Private Function fnBolTerminaActualizacionTipoCambio(ByVal pIarResultado As IAsyncResult) As Boolean
Dim sBolActualizacionExitosa As typBolResultadoFuncion
Dim sClsResultado = CType(pIarResultado, Messaging.AsyncResult)
Dim sIarResultado As fnBolAsyncCallActualizacionTipoCambio = CType(sClsResultado.AsyncDelegate, fnBolAsyncCallActualizacionTipoCambio)
CheckForIllegalCrossThreadCalls = False
sBolActualizacionExitosa = sIarResultado.EndInvoke(pIarResultado)
CheckForIllegalCrossThreadCalls = True
Return True
End Function
I hope they help.

DataReader ordinal-based lookups vs named lookups

Microsoft (and many developers) claim that the SqlDataReader.GetOrdinal method improves the performance of retrieving values from a DataReader versus using named lookups ie. reader["ColumnName"]. The question is what is the true performance difference if dealing with small, paged record sets? Is it worth the extra overhead of finding and referencing ordinal indexes throughout the code?
Microsoft recommends not calling GetOrdinal within a loop.
That would include indirect calls with the string indexer.
You can use GetOrdinal at the top of your loop put the ordinals in an array and have the indexes in the array be const or have an enum for them (no GetOrdinal at all) or use GetOrdinal into individual variables with descriptive names.
Only if your sets are small would I really consider this to be premature optimization.
It's apparently a 3% penalty.
Any difference will be more than outweighed by maintenance overhead.
If you have that much data that it makes a noticeable difference, I'd suggest you have too much data in your client code. Or this is when you consider use ordinals rather than names
Yes and no.
If you're dealing with a massive amount of data then you'd certainly benefit from using the ordinals rather than the column names.
Otherwise, keep it simple, readable, and somewhat safer - and stick with the column names.
Optimize only when you need to.
I created a wrapper for SqlDataReader that stores orindals in a dictionary with the column name as the key.
It gives me ordinal performance gains while keeping the code more readable and less likely to break if someone changes the column order returned from stored procedures.
Friend Class DataReader
Implements IDisposable
Private _reader As SqlDataReader
Private _oridinals As Dictionary(Of String, Integer)
Private Shared _stringComparer As StringComparer = StringComparer.OrdinalIgnoreCase 'Case in-sensitive
Public Sub New(reader As SqlDataReader)
Me._reader = reader
Me.SetOrdinals()
End Sub
Private Sub SetOrdinals()
Me._oridinals = New Dictionary(Of String, Integer)(_stringComparer)
For i As Integer = 0 To Me._reader.FieldCount - 1
Me._oridinals.Add(Me._reader.GetName(i), i)
Next
End Sub
Public Function Read() As Boolean
Return Me._reader.Read()
End Function
Public Function NextResult() As Boolean
Dim value = Me._reader.NextResult()
If value Then
Me.SetOrdinals()
End If
Return value
End Function
Default Public ReadOnly Property Item(name As String) As Object
Get
Return Me._reader(Me.GetOrdinal(name))
End Get
End Property
Public Function GetOrdinal(name As String) As Integer
Return Me._oridinals.Item(name)
End Function
Public Function GetInteger(name As String) As Integer
Return Me._reader.GetInt32(Me.GetOrdinal(name))
End Function
Public Function GetString(ordinal As Integer) As String
Return Me._reader.GetString(ordinal)
End Function
Public Function GetString(name As String) As String
Return Me._reader.GetString(Me.GetOrdinal(name))
End Function
Public Function GetDate(name As String) As Date
Return Me._reader.GetDateTime(Me.GetOrdinal(name))
End Function
Public Function GetDateNullable(name As String) As Nullable(Of Date)
Dim o = Me._reader.GetValue(Me.GetOrdinal(name))
If o Is System.DBNull.Value Then
Return Nothing
Else
Return CDate(o)
End If
End Function
Public Function GetDecimal(name As String) As Decimal
Return Me._reader.GetDecimal(Me.GetOrdinal(name))
End Function
Public Function GetBoolean(name As String) As Boolean
Return Me._reader.GetBoolean(Me.GetOrdinal(name))
End Function
Public Function GetByteArray(name As String) As Byte()
Return CType(Me._reader.GetValue(Me.GetOrdinal(name)), Byte())
End Function
Public Function GetBooleanFromYesNo(name As String) As Boolean
Return Me._reader.GetString(Me.GetOrdinal(name)) = "Y"
End Function
'Disposable Code
End Class

Web Service return value issue in VB.net

I have a Web Service with Just one Web Method that returns a boolean value and a function
When a client application consumes this web Service, I first want to return a value true and then continue with the remaining process.
I was googling and didn't find anything that I can understand. Please help me out. In one of the message posts I saw threading as one option. I tried that too.
Below is the code for the same I commented the threading part please help
<WebMethod()> _
Public Function HelloWorld(ByVal str As String) As Boolean
Dim status As Boolean = False
If str <> "" Then
'Dim t As New Thread(AddressOf ReturnWSStatus)
't.Start()
Me.DoItNow()
End If
Return status
End Function
Public Shared Function ReturnWSStatus() As Boolean
Return True
'Thread.Sleep(0)
End Function
You would need to do something like this:
<WebMethod()> Public Function HelloWorld(ByVal str As String) As Boolean
Dim status As Boolean = False
If str <> "" Then
Dim t As New Thread(AddressOf DoItNow)
t.Start()
return true
End If
End Function
Strictly speaking, the web method doesn't return before the additional processing starts, but it does return immediately after the new thread is launched, so the time difference is very small. Once you return from a method its execution is pretty much done, so whatever you want it to start needs to be started before the Return statement.

Using Delegates for handling an event

Sorry, that's the best subject I can come up with, if I understood the solution better, I could probably phrase a better subject line.
I am using a great grid control, Super List,l located here:
http://www.codeproject.com/KB/list/outlooklistcontrol.aspx?fid=449232&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=276
Before you read the problem, please note that you can download a very small VB.NET 2005 sample app which demos the problem:
http://dokmanovich.com/Documents/SuperListEvents.zip
Getting the answer to my question will, I hope, help me to understand dynamic events better in the context of what I am trying to accomplish.
The grid works like this: When you add a column to the grid, you specify the address of an event handler which will return the value at run time. In this case, the CC_ItemValueAccessor function. The latter function will be called with an input parameter which, in this case, is a "ToDo" object. Each ToDo object will be rendered as one row in the grid. The job of the CC_ItemValueAccessor function is to return the column value to be displayed by the grid for the row that corresponds to the passed-in ToDo object.
This works fine till I take it to the next step:
I want to dynamically create columns at run time. For example, I want to display the output of a datatable returned as a result of executing a user-specified SQL.
Using the earlier described static approach, I have one columnItemValueAccessor function responsible for returning the value of each column in the grid for the passed in row object. Now, since the columns are determined at run time based on the SQL returned results, I believe I need to write a generic handler that handles all columns, determines the name of the column that triggered this event and then returns the value for that column within the row object that is passed in as the sole parameter.
The problem is that the ItemValueAccessor function has a signature that only includes the row object and I do not know of a way to determine which column name is needed since all of the columns were hooked up to the same ItemValueAccessor function as the event handler.
I suspect that this is just a limitation of the control and that to overcome this problem I would have to enhance the underlying custom control, but that is likely beyond my current skills as it is an advanced control written in C# and I am a VB guy.
Here's the code:
Private Sub AddCcColumn()
Dim NewColumn As New BinaryComponents.SuperList.Column("CC", "CC", 110, AddressOf Cc_ItemValueAccessor)
_SuperList.Columns.Add(NewColumn)
End Sub
Private Function Cc_ItemValueAccessor(ByVal rowItem As Object) As Object
Dim ToDo As ToDo = CType(rowItem, SrToDoAndException).ToDo
Return ToDo.CCs.ToString
End Function
'---------------------------
And here are the signatures of the Column's instantiator method and the definition of the last parameter which is responsible for specifying the procedure that handles identifies the event handler responsible for returning the value of the column.
Public Sub New(ByVal name As String, ByVal caption As String, ByVal width As Integer, ByVal columnItemValueAccessor As BinaryComponents.SuperList.ColumnItemValueAccessor)
Member of BinaryComponents.SuperList.Column
Public Sub New(ByVal object As Object, ByVal method As System.IntPtr)
Member of BinaryComponents.SuperList.ColumnItemValueAccessor
Does anyone have any suggestions or am I stuck? I would really love to utilize the fantasic grouping capabilities of this control so I can display dynamic output that allows the user to group the dynamic output of a SQL by any column that they want.
I addressed the question to the author at the above site but it has gone unanswered. This is a desperate attempt to find a way to do this.
Thanks for bearing with me. I hope this question isn't rejected based on the fact that I refer to a third party control. My hope is that the answer lies in a better understanding of delegates, a more universal topic.
I used a lambda function, as Matthew suggested. Here is the code from the dynamic approach:
Private Sub btnDynamic_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDynamic.Click
ListControl1.Columns.Clear()
For Each DataCol As DataColumn In _ds.dtbPerson.Columns
' Get the column name in a loop variable - it needs to be in loop scope or this won\'t work properly'
Dim colName = DataCol.ColumnName
' Create the function that will be called by the grid'
Dim colLambda As ColumnItemValueAccessor = Function(rowItem As Object) General_ItemValueAccessor(rowItem, colName)
' Setup each column in the grid'
Dim NewColumn As New BinaryComponents.SuperList.Column(DataCol.ColumnName, DataCol.ColumnName, 220, colLambda)
ListControl1.Columns.Add(NewColumn)
Next
End Sub
Private Function General_ItemValueAccessor(ByVal rowItem As Object, ByVal colName As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(colName).ToString
End Function
Here's a quick primer on how it works:
Each time through the loop the lambda function is creating a new callback function for each column that looks something like this:
Class Func1
Dim colName1 As String = "PersonId"
Private Function General_ItemValueAccessor1(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.colName1).ToString
End Function
End Class
Class Func2
Dim colName2 As String = "LastName"
Private Function General_ItemValueAccessor2(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.colName2).ToString
End Function
End Class
... for however many columns you have - 3 in this case.
You need the colName variable within the loop and not use just DataCol.ColumnName directly in the lambda. Otherwise, when the grid gets around to calling the callback functions, that DataCol variable would be equal to the last value from the collection (or Nothing) for all the callback functions.
Basically, it would do this and you wouldn't get what you expected:
Class Func
Dim DataCol1 = DataCol
Private Function General_ItemValueAccessor1(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.DataCol1.ColumnName).ToString
End Function
Private Function General_ItemValueAccessor2(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.DataCol1.ColumnName).ToString
End Function
...
End Class
Hope that helps. Good luck.
The problem is that the ItemValueAccessor function has a signature that only includes the row object and I do not know of a way to determine which column name is needed since all of the columns were hooked up to the same ItemValueAccessor function as the event handler.
Okay, I haven't used that control in the past, and I'm really a C# person. But I think you may be able to accomplish this by creating a new lambda function for each column. Something like:
Private Sub AddCcColumn(ByVal sender As System.Object As System.String)
colLambda = (Function(rowItem As Object) Cc_InternalItemValueAccessor(columnName, rowItem))
Dim NewColumn As New BinaryComponents.SuperList.Column("CC", "CC", 110, colLambda)
_SuperList.Columns.Add(NewColumn)
End Sub
Then, colLambda will fit the signature, while your internal Cc_InternalItemValueAccessor gets the info it needs. Totally untested, but I think the basic idea works.