Will statements or expressions execute after a return statement in VB.net? - vb.net

Ok, I was rooting around in one of our company apps which is done in VB.net. I'm not familiar with VB.net (I do stuff in C#) so I'm asking this question: Does the code after the clean up comment execute?
Public Function DoesUserHavePermission(ByVal UserID As Integer, ByVal ActionID As Integer) As Boolean
' some extra code re: getting data
Return UserHasPermission
'-Clean Up-
MySqlCommand.Dispose()
MySqlConnection.Dispose()
RowCount = Nothing
End Function
It is my understanding once you say return, you give the calling function control again. Is this a VB.Net oddity which I have to accept or a giant WTF?

The statements after the Clean up comment will not execute. This is a candidate for enclosure within Try/Catch/Finally.

Not unless there's some control logic you omitted in your example

The code should be (the clean up that is) wrapped inside of a finally statement by using a try catch exception:
pseudo:
try
'make conn
catch exception
finally
mysqlCmd.Dispose
....
end try
Is it possible it will still run..possibly...I used to write VB.net and it has been quite some time but I do remember oddities like that. I can't give you a sure answer as this is / was very bad practice. What you can do is clean it up and set some break points in y our code and debug. See if the code comes back to it...

Short answer: The code below the return will never execute.
That looks like translated code. Like someone took a C# snippet from the web and tried to write it in VB for VS 2003 (before VB supported the USING statement, but while C# did).
where the MySqlConnection and MySqlCommand are new'd up should be put in USING blocks and the Dispose() lines turned into END USING.
Where possible, use USING over TRY/FINALLY to ensure cleanup of IDisposable objects.
using mySqlConnection as New SqlConnection(connectionString)
mySqlConnection.Open
using mySqlCommand as New SqlCommand(commandString, mySqlConnection)
'do something that may fail'
return UserHasPermission
end using 'disposes mySqlCommand'
end using 'closes/disposes mySqlConnection'
You can use this pattern for SqlTransactions too. (Place after mySqlConnection.Open)
using myTerribleVariableName as SqlTransaction = mySqlConnection.BeginTransaction
'do something that may fail - multiple SqlCommands maybe'
'be sure to reference the transaction context in the SqlCommand'
myTerribleVariableName.Commit
end using 'disposes. rollsback if not commited'
Oh, and you can delete the RowCount = Nothing statement.

That to me is a giant WTF and a very difficult thing to miss, normally peer code review can catch that, I do not understand why a return from the function is placed earlier on prior to the cleanup. That could have been done during the testing of the code where the programmer was wanting to test the function first and decided to ignore the cleanup code by returning from it quickly enough, I suspect the cleanup code could be lengthy, ie. maybe it is throwing an exception that is not properly caught and wanted to ignore it hence a need to return immediately...That is an (un) intentional side effect of introducing a leak as the resource is not cleaned up properly thereby masking the real problem...that's my take on it.
Hope this helps,
Best regards,
Tom.

The code as presented will not do anything after the return statement. VB.NET and C# are similar in that fashion.
Its possible that this code was written by a VB6 programmer, trusting in old paradigms, or possibly this was the work of the upgrade tool, porting code from VB6 to VB.NET.

Related

Why does defining a variable of type of Smo.Server cause a 10 second delay

Bear with me here, ok!!
We use SMO a lot to do all kinds of things, including to check for the presence of particular stored procedures in the database. So we have a method in our data access class called HasProc, which returns a boolean. It's in a part of the application that hasn't been changed for over a year, possibly two years.
Lately, it's been taking ages (10s) to return a value, and I've been trying to pin down why.
It turns out that even defining the variable that will hold the SMO Server (not instantiating it, just defining it) causes a 10s delay in the code arriving into the function.
Here's the relevant bit of the code, which just returns True now, for clarity:
Public Function HasProc(ByVal storedProcName As String) As Boolean
Dim s As Microsoft.SqlServer.Management.Smo.Server
Return True
End Function
In Visual Studio 12, stepping through the code using F11, the 10 second delay happens before the code highlight arrives at Public Function etc...
If I comment out the Dim statement, it all runs instantly.
Even more weirdly, if I disable my ethernet adaptor, the delay does not occur.
This is reproducible across three computers. I'm using VS2012, and SMO v11, to which we recently upgraded in order to support SQL Server 2012.
The other thing is that the delay happens even if the Return True statement is before, rather than after the Dim statement.
Any ideas?
This would happen if the static initializer for that class performs network IO (which is generally a bad idea).
If you pause the debugger during the delay, you can find out exactly what it's doing.

With... End With vs Using in VB.NET

I just found out that like C#, VB.NET also has the using keyword.
Until now I thought it didn't have it (stupid of me, I know...) and did stuff like this instead:
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
What are the implications of this compared to doing it with a using statement like this
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
UPDATE:
I should add that I am familiar with what the using statement does in that it disposes of the object when the construct is exited.
However, as far as I understand the With New ... construct will have the object mark the object as ready for garbage collection when it goes out of scope.
So my question really is, is the only difference the fact that with using I will release the memory right away, whereas with the With construct it will be released whenever the GC feels like it? Or am I missing something bigger here?
Are there any best practice implications? Should I go and rewrite all the code with I used With New MyDisposableObject() ... End With as Using o as New MyDisposableObject()?
With Statements/Blocks
However, as far as I understand the With New ... construct will have the object mark the object as ready for garbage collection when it goes out of scope.
This is both true and not true. It is true in the sense that all objects are "marked" (purists might quibble with this terminology, but the details are not relevant) as ready for garbage collection when they go out of scope. But then in that sense, it is also not entirely true, as there's nothing special about the With keyword with respect to this behavior. When an object goes out of scope, it is eligible for garbage collection. Period. That's true for method-level scope and it's true for block-level scope (e.g., With, For, Using, etc.).
But that's not why you use With. The reason is that it allows you to set multiple properties in sequence on a deeply-nested object. In other words, assume you have an object on which you want to set a bunch of properties, and you access it this way: MyClass.MemberClass.AnotherMemberClass.Items(0). See all those dots? It can (theoretically) become inefficient to write code that has to work through that series of dots over and over to access the exact same object each time you set a property on it. If you know anything about C or C++ (or any other language that has pointers), you can think of each of those dots as implying a pointer dereference. The With statement basically goes through all of that indirection only once, storing the resulting object in a temporary variable, and allowing you to set properties directly on that object stored in the temporary variable.
Perhaps some code would help make things clearer. Whenever you see a dot, think might be slow!
Assume that you start out with the following code, retrieving object 1 from a deeply-nested Items collection and setting multiple properties on it. See how many times we have to retrieve the object, even though it's exactly the same object every time?
MyClass.MemberClass.AnotherMemberClass.Items(0).Color = Blue
MyClass.MemberClass.AnotherMemberClass.Items(0).Width = 10
MyClass.MemberClass.AnotherMemberClass.Items(0).Height = 5
MyClass.MemberClass.AnotherMemberClass.Items(0).Shape = Circle
MyClass.MemberClass.AnotherMemberClass.Items(0).Texture = Shiny
MyClass.MemberClass.AnotherMemberClass.Items(0).Volume = Loud
Now we modify that code to use a With block:
With MyClass.MemberClass.AnotherMemberClass.Items(0)
.Color = Blue
.Width = 10
.Height = 5
.Shape = Circle
.Texture = Shiny
.Volume = Loud
End With
The effect here, however, is identical to the following code:
Dim tempObj As MyObject = MyClass.MemberClass.AnotherMemberClass.Items(0)
tempObj.Color = Blue
tempObj.Width = 10
tempObj.Height = 5
tempObj.Shape = Circle
tempObj.Texture = Shiny
tempObj.Volume = Loud
Granted, you don't introduce a new scope, so tempObj won't go out of scope (and therefore be eligible for garbage collection) until the higher level scope ends, but that's hardly ever a relevant concern. The performance gain (if any) attaches to both of the latter two code snippets.
The real win of using With blocks nowadays is not performance, but readability. For more thoughts on With, possible performance improvements, stylistic suggestions, and so on, see the answers to this question.
With New?
Adding the New keyword to a With statement has exactly the same effect that we just discussed (creating a local temporary variable to hold the object), except that it's almost an entirely pointless one. If you need to create an object with New, you might as well declare a variable to hold it. You're probably going to need to do something with that object later, like pass it to another method, and you can't do that in a With block.
It seems that the only purpose of With New is that it allows you to avoid an explicit variable declaration, instead causing the compiler to do it implicitly. Call me crazy, but I see no advantage in this.
In fact, I can say that I have honestly never seen any actual code that uses this syntax. The only thing I can find on Google is nonsense like this (and Call is a much better alternative there anyway).
Using Statements/Blocks
Unlike With, Using is incredibly useful and should appear frequently in typical VB.NET code. However, it is very limited in its applicability: it works only with objects whose type implements the IDisposable interface pattern. You can tell this by checking to see whether the object has a Dispose method that you're supposed to call whenever you're finished with it in order to release any unmanaged resources.
That is, by the way, a rule you should always follow when an object has a Dispose method: you should always call it whenever you're finished using the object. If you don't, it's not necessarily the end of the world—the garbage collector might save your bacon—but it's part of the documented contract and always good practice on your part to call Dispose for each object that provides it.
If you try to wrap the creation of an object that doesn't implement IDisposable in a Using block, the compiler will bark at you and generate an error. It doesn't make sense for any other types because its function is essentially equivalent to a Try/Finally block:
Try
' [1: Create/acquire the object]
Dim g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ... etc.
End Try
Finally
' [3: Ensure that the object gets disposed, no matter what!]
g.Dispose()
End Finally
But that's ugly and becomes rather unwieldy when you start nesting (like if we'd created a Pen object that needed to be disposed as well). Instead, we use Using, which has the same effect:
' [1: Create/acquire the object]
Using g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ...etc.
End Using ' [3: Ensure that the object gets disposed, no matter what!]
The Using statement works both with objects you are first acquiring (using the New keyword or by calling a method like CreateGraphics), and with objects that you have already created. In both cases, it ensures that the Dispose method gets called, even if an exception gets thrown somewhere inside of the block, which ensures that the object's unmanaged resources get correctly disposed.
It scares me a little bit that you have written code in VB.NET without knowing about the Using statement. You don't use it for the creation of all objects, but it is very important when you're dealing with objects that implement IDisposable. You definitely should go back and re-check your code to ensure that you're using it where appropriate!
By using With...End With, you can perform a series of statements on a specified object without specifying the name of the object multiple times.
A Using block behaves like a Try...Finally construction in which the Try block uses the resources and the Finally block disposes of them.
Managed resources are disposed by the garbage collector without any extra coding on your part.
You do not need Using or With statements.
Sometimes your code requires unmanaged resources. You are responsible for their disposal. A Using block guarantees that the Dispose method on the object is called when your code is finished with them.
The difference is the Using With...End End
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
Calls cn.Dispose() automatically when going out of scope (End Using). But in the With New...End
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
.Dispose() is not explicitly called.
Also with the named object, you can create watches and ?cn in the immediate window. With the unnamed object, you cannot.
Using connection... End Using : Be careful !!!
This statement will close your database connection !
In the middle of a module or form(s), i.e.adding or updating records, this will close the connection. When you try to do another operation in that module you will receive a database error. For connections, I no longer use it. You can use the Try... End Try wihthouth the Using statement.
I open the connection upon entry to the module and close it it upon exit. That solves the problem.

Correct error-handling practices for the data-layer

What are good things to check for, with respect to error-handling, when you are dealing with the data-access-layer? For example, let's assume I have this function..
Public Function UserExists(ByVal userName As String) As DataTable
Dim dt As Object = Nothing
Dim arSqlParameters(0) As SqlParameter
arSqlParameters(0) = New SqlParameter("#UserName", SqlDbType.NVarChar, 50)
arSqlParameters(0).value = userName
dt = ABC.APP.DAL.DALHelper.ExecuteDatatable(ConnectionString, CommandType.StoredProcedure, "dbo.aspnet_sprGetUserByUsername", arSqlParameters)
Return dt
End Function
This seems like very lazy and unsafe coding. How would you go about ensuring that your code elegantly handles anything unexpected in a situation like this?
I'm new to vb.net and the app that I'm working on has no error handling, so I figured this would be the best place to look for advice. Thanks in advance :)
Not sure why you're not declaring dt as a datatable - what is the motiviation for "dim dt as object = nothing"?
Really the only line that can reasonably fail is the "dt=ABC.APP.DAL...." call.
In that line, you could have a few errors:
The stored procedure or parameter
names are wrong. This should be
caught at design-time (not by a
built-in checking mechanism, but the
first time that you try to run the
code)
An error occurs in the stored
procedure. Sprocs use deferred name
resolution, which can lead to runtime
errors if (for instance) objects
don't exist at the time that the
sproc is called. Again, this is most
likely to rear it's head in testing.
A deadlock. In this case, you should
catch and resubmit the batch.
Here's an intro and set of links
on handling SQL errors in application
code.
A parameter that is passed is
invalid (too long, wrong datatype,
etc). This should be checked
before you call the sproc.
This might be of use to you...
.NET Framework Developer's Guide - Design Guidelines for Exceptions
Opinions are likely to vary wildly on a topic like this, but here's my take. Only try to deal with the exceptions that you relate to this area. That's a vague statement, but what I mean is, did the user pass a string with more chars than the column in the db. Or did they violate some other business rule.
I would not catch errors here that imply the database is down. Down this far in the code, You catch errors that you can deal with, and your app needs it's database. Declare a more global exception handler that logs the problem, notifies someone, whatever... and present the user with a "graceful" exit.
I don't see any value in catching in each method a problem with the database. You're just repeating code for a scenario that could bomb any part of your datalayer. That being said, if you choose to catch db errors (or other general errors) in this method, at least set the innerexception to the caught exception if you throw a new exception. Or better, log what you want and then just "throw", not "throw ex". It will keep the original stack trace.
Again, you will get a lot of varying thoughts on this, and there is no clear right and wrong, just preferences.
looking inside Open Source ORM solutions' code (Subsonic, nHibernate) will help you.
By my limited knowledge I think error related to connections, connection timeouts etc. should be passed as such because DAL cannot do much about it. Error related to the validations (like field lengths, datatypes) etc should be returned with appropriate details. You may provide validation methods (Subsonic contains it) that validate the field values and returns the appropriate error details.
I've put a lot of thought into this as well. A lot depends on the particular database, so depending on if you are using SQL2000 or SQL2005+ you will either be doing return codes, RAISERROR or TRY-CATCH in the stored procedure.
RAISERROR is preferably to return codes, because developers using the stored procedure get more information. Optimally you'd pick numbers 50000 and up and register the corresponding messages, but this is a lot of work just to communicate what can be communicated in the text of the RAISERROR call
The return code is uninterperatable without reading the source code of the stored procedure. a return value of 0 might be success, failure, 0 rows affected, the just generated primary key, or that no return code was set depending on the whims of the stored procedure writer that day. Also, ADO.NET returns row count from ExecuteNonQuery, so some developers will find it hard to quickly discover the return code.
Ad hoc solutions are also bad, eg.
IF ##Error>0
SELECT 'Something bad happened'
If you have the option of using CLR stored procedures, then C# style error handling comes into play.
So add RAISERROR to your stored procedures, then catch SqlException, report to the user anything that really is a user data entry Validation, log anything that is a developer abusing the API, and maybe attempt a re-try for connection or execution timeouts.
IF #Foo =42
BEGIN
RAISERROR ( 'Paramater #foo can''t be 42',
16, -- Severity = Misc. User Error.
1 -- State. == ad hoc way of finding line of code that raised error
) ;
RETURN -1; --Just because some developers are looking for this by habit
END

VB.NET - How to get the instance used by a With statement in the immediate window

VB.NET has a very handy "with" statement, but it also lets you use it on an unnamed variable, like this:
With New FancyClass()
.Level = "SuperSpiffy"
.Style = Slimming
.Execute()
End With
Is there a way to get at the "hidden" instance, so I can view its properties in the Immediate window? I doubt I'll get it in the watch windows, so immediate is fine.
If you try to access the instance the same way (say, when .Execute() throws an exception) from the Immediate window, you get an error:
? .Style
'With' contexts and statements are not valid in debug windows.
Is there any trick that can be used to get this, or do I have to convert the code to another style? If With functioned more like a Using statement, (e.g. "With v = New FancyClass()") this wouldn't pose a problem.
I know how With is working, what alternatives exist, what the compiler does, etc. I just want to know if this is possible.
As answered, the simple answer is "no".
But isn't another way to do it: instead of declaring and then cleaning up the variable is to use the "Using".
Using fc as new FancyClass()
With fc
.Level = "SuperSpiffy"
.Style = Slimming
.Execute()
End With
End Using
Then you can use fc in the immediate window and don't have to remember to write a
fc=nothing
line.
Just some more thoughts on it ;)
What's wrong with defining a variable on one line and using it in a with-statement on the next? I realise it keeps the variable alive longer but is that so appalling?
Dim x = new SomethingOrOther()
With x
.DoSomething()
End With
x = Nothing ' for the memory conscious
Two extra lines wont kill you =)
Edit: If you're just looking for a yes/no, I'd have to say: No.
I hope there really isn't a way to get at it, since the easy answer is "no", and I haven't found a way yet either. Either way, nothing said so far really has a rationale for being "no", just that no one has =) It's just one of those things you figure the vb debugger team would have put in, considering how classic "with" is =)
Anyway, I know all about usings and Idisposable, I know how to fix the code, as some would call it, but I might not always want to.
As for Using, I don't like implementing IDisposable on my classes just to gain a bit of sugar.
What we really need is a "With var = New FancyClass()", but that might just be confusing!
You're creating a variable either way - in the first case (your example) the compiler is creating an implicit variable that you aren't allowed to really get to, and the in the second case (another answer, by Oli) you'd be creating the variable explicitly.
If you create it explicitly you can use it in the immediate window, and you can explicitly destroy it when you're through with it (I'm one of the memory conscious, I guess!), instead of leaving those clean up details to the magic processes. I don't think there is any way to get at an implicit variable in the immediate window. (and I don't trust the magic processes, either. I never use multiple-dot notation or implicit variables for this reason)

Linq Update Problem

I'm having some problems updating the database using Linq...
Public Shared Function Save(ByRef appointment As MyLinq.Appointment, ByRef db As MyEntities) As Boolean
If appointment.id = 0 Then
db.AddToAppointments(appointment)
Else
db.AttachTo("Appointments", appointment)
'db.ApplyPropertyChanges("Appointments", appointment)
End If
Return db.SaveChanges() > 0
End Function
So Insert works fine, i have tryed both lines of code for the update with no sucesss... The first one goes ok but no update is performed, the second one throws an exception...
Can someone point out what i am missing?
EDIT:
Sorry for the late reply... I had some internet connection problems...
I had to "make it work", so now my update code is fecthing the record from the database, updating and then executing "SaveChanges" method. It works but I am not happy having to query the database to perform an Update... If you have any idea how I could do this without an update I would appreciate :)
Chris: It was a nice try, but my refresh method only allows me to choose "RefreshMode.ClientWins" or "RefreshMode.StoreWins" I tried with ClientWins with no success...
Razzie: I am sorry but i did not save the exception and it no longer occurs... It was saying that my record did not have a key associated (or something similar)
Jon Skeet: In Vb.Net we have to specify if the parameter goes ByVal or ByRef, we can't omit like in C#
The code you have doesn't look exactly like what I'm used to (linq to sql), but it does look a little similar; Is this Entity Framework?
I know with Linq to SQL, simply attaching an object to the data context isn't enough, you also have to make sure that the data context knows what the original values are so it knows which columns to update. In Linq to SQL that can be achieved like this:
db.Refresh(RefreshMode.KeepCurrentValues, appointment)
Maybe look around and see if you can achieve something similar in whatever framework you are using.
The ApplyPropertyChanges() call is important otherwise the item you are attaching is assumed to be in an unchanged state. However... for ApplyPropertyChanges to work properly the original object must exist in the ObjectContext which means either querying for it again (which I think you are now doing) or using the same object context that you originally pulled the item from.
Some more info here - http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.applypropertychanges.aspx