VB .Net - TransactionScope aborts when Using is outside Try/Catch - vb.net

The following method is called from within a loop:
Public Sub ExampleAbort()
Using trans As New TransactionScope(TransactionScopeOption.Required, New TransactionOptions With {.IsolationLevel = IsolationLevel.ReadUncommitted, .Timeout = New TimeSpan(0, 10, 0)})
Try
DoSomeTransationalStuffHere()
trans.Complete()
Catch ex As Exception
ShowError(ex.Message)
Throw
End Try
End Using
End Sub
This will lead to the DTS aborting the transaction after the first item. If I place the 'Using' statement within the Try/Catch block, everything works. Can someone please explain this behavior? I was under the assumption that Using-blocks ALWAYS Dispose'd no matter how you return from a method.
Best regards,
Goran

Related

How to properly close a WCF Netnamedpipebinding Channel?

I have a WCF Netnamedpipebinding from my application to an Office Addin. I have noticed that when the office app is busy doing something else that my application locks up when using a WCF method. I have added an example of my code. It appears that the code stops and waits with the channel.close method.
Is the solution to change channel.close to channel.BeginClose ?
What is the the state object I need to pass in to the BeginClose method?
Public Function RequestPersonStatus(ByVal id As String, ByVal email As String)
Using factory As New ChannelFactory(Of IToOffice)(New NetNamedPipeBinding(), New EndpointAddress("net.pipe://localhost/" + XXXXXX))
Dim OfficeChannel As IToOffice = factory.CreateChannel()
Try
OfficeChannel.RequestPersonStatus(id:=id, email:=email)
Catch ex As Exception
Return False
Finally
CloseChannel(CType(OfficeChannel, ICommunicationObject))
End Try
End Using
Return True
End Function
and the closeChannel
Private Sub CloseChannel(ByVal channel As ICommunicationObject)
Try
If channel.State = CommunicationState.Opened Then
Dim caller As New AsyncCallback(AddressOf callback)
channel.BeginClose(caller, New Object)
' channel.Close()
End If
Catch ex As Exception
Log(LogTypes.AllExceptions, "CloseChannel - Error closing the channel. ", ex.ToString)
Finally
channel.Abort()
End Try
End Sub
There seems to be a lot of discussion on what and when to clean up / Dispose / close down channels. I am just posting here what I am now doing and thus my answer to my question.
Private Sub CloseChannel(ByVal channel As ICommunicationObject)
Try
If channel.State <> CommunicationState.Closed AndAlso channel.State <> CommunicationState.Faulted Then
channel.BeginClose(Sub(asr)
Try
channel.EndClose(asr)
Catch
channel.Abort()
End Try
End Sub, Nothing)
Else
channel.Abort()
End If
Catch commEx As CommunicationException
channel.Abort()
Catch ex As Exception
channel.Abort()
Finally
End Try
End Sub
As far as I know, most of the cases like the timeout error/connection/communication error are caused by that the channel/client proxy is not properly closed. Putting the client proxy/Service Channel in a using block will eliminate the problem.
using (ServiceReference1.ServiceClient client=new ServiceClient())
{
var result = client.Test();
Console.WriteLine(result);
}
The Using statement is useful for automatically closed the service proxy/service communication channel after completing the invocation. Besides, Service client proxy is similar to the communication channel created by the ChannelFactory.
Feel free to let me know if there is anything I can help with.

Exception handling with Async Task functions

I am beginning to learn about Async / Task functions for running cancellable SQL queries in VB.NET.
I have the following code in a class library which runs two tasks and does not have any exception handling, as I would like to handle this in the application that calls the class library. I have the following code in the class library.
Public Async Function DirectoryList(ct As CancellationToken) As Task(Of List(Of Directory))
ct.ThrowIfCancellationRequested()
Dim ds As DataSet
Dim dirs As List(Of Directory)
Dim ctUnregister As CancellationTokenRegistration
ds = Await Task.Run(Function()
Using newConnection = New SqlConnection(Me.InitializationData.ConnectionString)
Using sqlAdapter = New SqlDataAdapter("DirectoryList", newConnection)
ctUnregister = ct.Register(Sub() sqlAdapter.SelectCommand.Cancel())
With sqlAdapter
.SelectCommand.CommandType = CommandType.StoredProcedure
.SelectCommand.CommandTimeout = Me.InitializationData.CommandTimeout
End With
Dim newDataSet As DataSet = New DataSet()
sqlAdapter.Fill(newDataSet)
Return newDataSet
End Using
End Using
' Remove the registration we set earlier so the cancellation token can be used normally.
ctUnregister.Dispose()
End Function, ct)
dirs = Await Task.Run(Function()
Dim dirsResult As New List(Of Directory)
Dim tbl As DataTable = ds.Tables(0)
For Each row As DataRow In tbl.Select()
' process the data
ct.ThrowIfCancellationRequested()
Next
Return dirsResult
End Function, ct)
Return dirs
End Function
I then call it as follows:
Try
dirs = Await databaseLibrary.DirectoryList(cts.Token)
MsgBox("Query complete!")
Catch ex As System.Data.SqlClient.SqlException
MsgBox("Cancelled (SQL)")
Catch ex2 As OperationCanceledException
MsgBox("Cancelled")
Catch ex3 As Exception
MsgBox("Cancelled")
End Try
Functionally it seems to work as expected - I can cancel the requests and exceptions are thrown as expected.
However I would like to handle the exceptions so I can gracefully cancel the tasks, but even when running in Debug mode within the IDE, the app still breaks and the exception (e.g. SqlException) is shown within the IDE. If I step on, eventually the Catch logic runs.
When the application is run outside of the IDE, the exception handling works as expected.
This seems different to the normal behaviour when running in the debugger- normally the exception handling runs but only breaks if the exception is unhandled.
Why is this behaviour different, presumably because of the Async functions?
when running in Debug mode within the IDE, the app still breaks and the exception (e.g. SqlException) is shown within the IDE.
Why is this behaviour different, presumably because of the Async functions?
Exceptions thrown by asynchronous functions are not caught directly by the catch. What actually happens is that the exception is caught by a compiler-generated state machine, and that exception is placed on the returned Task. Later, when that task is awaited, the exception is re-raised, and then can be caught by the catch.
However, this "indirection" in exception handling means that the IDE does kind of freak out when the exception is initially thrown. As far as it can tell, there is no catch in your code that is going to catch it, so that's why it breaks and displays the exception. It doesn't know that the compiler-generated code will catch it. You can tell the IDE not to worry about uncaught exceptions.

will everything automatically close in this code if there is an exception

three questions please
1) If there is an exception in the try below will the request stream automatically close as it is in a using
2)do I even need the requestStream.Close() and requestStream.Dispose() as it is in a using?
3) do I need to close the System.Net.FtpWebRequest?
Try
Dim rqst As System.Net.FtpWebRequest = DirectCast(System.Net.WebRequest.Create("ftp://1.com/text.txt"), System.Net.FtpWebRequest)
rqst.Credentials = New System.Net.NetworkCredential("useb", "pass")
rqst.Method = System.Net.WebRequestMethods.Ftp.UploadFile
'Throw New ApplicationException("Exception Occured")
Dim fle() As Byte = System.IO.File.ReadAllBytes("C:\test.txt")
Using requestStream As Stream = rqst.GetRequestStream()
requestStream.Write(fle, 0, fle.Length)
requestStream.Close() 'do I need this?
requestStream.Dispose() 'do I need this ?
End Using
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
No you dont need if you are using using. As using itself is used to dispose of. Also the reason for the "using" statement is to ensure that the object is always disposed correctly, and it doesn't require explicit code to ensure that this happens.
Dispose method is called immediately when control flow exits the using block.
Yes. If the exception occurs while executing code inside the using statement, the stream will be disposed before it goes to the Catch block.

how do I clean up after a StreamWriter during an exception?

I'm trying to clean-up after an exception, and I'm not sure how to handle a StreamWriter.
Dim sw As StreamWriter
Try
''// stuff happens
somethingBad1() ''//Sometimes throws an exception
sw = New StreamWriter(File.Open("c:\tmp.txt", FileMode.Create))
''// stuff happens
somethingBad2() ''//Also sometimes throws an exception
sw.Write("Hello World")
sw.Flush() ''//Flush buffer
sw.Close() ''//Close Stream
Catch ex As Exception
sw = Nothing
Finally
sw = Nothing
end try
If somethingBad1 throws an exception, I don't need to do anything to sw; however, if somathignBad2 happens, sw has already been created and I need to close it. But How do I know if sw has been created or not?
''//stuff happens but you don't care because you didn't instantiate
''// StreamWriter yet
somethingBad1() ''//Sometimes throws an exception
Using sw As New StreamWriter("test.dat")
''// stuff happens
somethingBad2() ''//Also sometimes throws an exception
''//as you are in a using statement the sw.Dispose method would be called
''//which would free the file handle properly
sw.Write("Hello World")
End Using
Only do the try after assigning the sw variable (in your sample). Or use a using statement.
But as a general rule, you should close the StreamWriter (if not using it with using), and not just assign Nothing to it. Also, catching all exceptions should be avoided, only handle exception which you know how to handle gracefully.
Darin has it right, but just one stylistici point to expand on Pavel Minaev's comment: unlike VB6, in VB.Net setting your sw reference to Nothing has no real effect. You really don't need to do it. What you could do is have code like this in your finally block:
Finally
''# test
If sw IsNot Nothing Then sw.Dispose()
End
And that would take care of all the required cleanup (including what you've show of the catch block). You wouldn't even need to close the stream in your main code. But Using blocks are normally the better way to handle this.

a simple question about the InsertOnSubmit

if the code look like:
dim db = new context.mytable
db.somefield = something
context.insertonsubmit(db )
try
context.save
catch ex as exception
''----????
end try
how to I remove db from the context if it goes into the catch?
One idea would be to wrap the whole process in the try catch, so the if an exception is thrown the context gets disposed thus object is no longer in the context., something like:
try
dim context = new //LINQ-To-SQL context
dim db = new context.mytable
db.somefield = something
context.insertonsubmit(db )
context.save
catch ex as exception
context.dispose();
end try
Note: I have not tried this so you will have to test it.