VB.Net initializing datasets - vb.net

When did Microsoft start forcing datasets to be initialized with a "New" statement? My company has a website that was started many years ago and a lot of the datasets were declared with a statement like
Dim someDataset as Dataset = Nothing
This code has worked for a long time but we recently started receiving errors stating Value cannot be null. Parameter name: dataset.
I've done my best to update this old code but I'm not aware of any updates to the libraries we are using and I'm trying to identify what triggered this error to begin with. Thank you
I'd like to emphasize that no changes were made to the code before the error started occurring as unlikely as that might sound. It is a large app and datasets are used throughout it in a variety of ways. It has been in production for many years and worked as expected before this error started occurring recently.

That has not changed since Day 1 of .NET. All reference types must be created with a New statement somewhere or else they will remain a null reference (Nothing).
It sounds like some other part of the app that used to create the dataset has been removed or changed so that it sometimes returns Nothing.

There is a difference between declaring and instantiating.
This line declares a DataSet:
Dim myDataSet As DataSet
Note: Since you only declared a DataSet object, it is not set to an instance, therefore it is Nothing.
This line instantiates a DataSet:
myDataSet = New DataSet()
Often you will see the lines put together, like this:
Dim myDataSet = New DataSet()
If you only declare a DataSet, then you must be sure to check if it is Nothing before you use it, like this:
If myDataSet Is Not Nothing Then
' Use myDataSet because there is an instance of it
End If
Note: You should ALWAYS check if the return type of a Function is Nothing or not.

Related

Does OleDbTransaction.Commit() closes the connection?

I need to run a number of queries as part of a transaction.
There's a method in my project, creatively named RunQuery(), that concentrates the database queries, so I'll be using it. It has four parameters:
a string indicating which database to run the query on,
a string containing the query,
a table name for when the result needs to be a data set,
an Enum that indicates what kind of query/results is wanted: Select query returning a data reader, Select query returning a data set, Insert/Update/Delete query.
(If you need more detail, I'll supply it gladly. I'll keep this short-ish for now.)
The point is that when you want to run a query, you don't have to worry about the connection or command objects, you just write your query and call RunQuery(). Fine.
Now, I've added a new ByRef parameter to RunQuery(), an IDbTransaction to track the transaction. It needs to be handled at least partially outside RunQuery(), if only to commit after the very last call, but on the first call it's set at Nothing.
I've also added an item to the Enum so RunQuery() knows it has to deal with a transaction.
My code looks like this:
Dim z_lisQuery As New List(Of String)
' [...] Filling z_lisQuery with queries
Dim z_dtrTransaction As IDbTransaction = Nothing
Dim z_blnExecutionOk As Boolean = True
For Each z_strQuery As String In z_lisQuery
z_blnExecutionOk = z_blnExecutionOk And RunQuery(p_strDbId,
z_strQuery,
"",
z_dtrTransaction,
QueryAction.ExecutionTransaction)
If Not z_blnExecutionOk Then
Exit For
End If
Next
If z_blnExecutionOk Then
z_dtrTransaction.Commit()
End If
z_dtrTransaction?.Connection.Dispose()
z_dtrTransaction?.Dispose()
(A Rollback() is executed within RunQuery() if something goes wrong.)
When I run that and no errors happen, everything goes fine until the penultimate line:
z_dtrTransaction?.Connection.Dispose() throws an exception because z_dtrTransaction.Connection is Nothing.
The obvious workaround is to use z_dtrTransaction?.Connection?.Dispose(), so that's not what I'm puzzled about.
What I'm puzzled about is that z_dtrTransaction.Connection is still a functional OleDbConnection object when execution reaches z_dtrTransaction.Commit(). But after z_dtrTransaction.Commit() is executed, z_dtrTransaction.Connection is Nothing.
I can see the point of that, but the language reference doesn't seem to indicate that it should happen that way and I haven't found a reference to that way of doing things.
Is it officially stated somewhere that this behavior is the normal one? Or is it just with OleDbConnection and not with SqlConnection, for instance?
(Even if it is, obviously I'm keeping z_dtrTransaction?.Connection?.Dispose() because I'm not entirely sure what happens in case of a rollback.)

Object cannot be cast from DBNull to other types with visual basic code

I have added dummy data to my SQL database.
When I try to run the VB it comes back with a null error.
What I have done is delete the dummy data from the database so it not reading the null value anymore.
Even after deleting it the VB file is still throwing the error like the null values are still there.
I have run a sql script to check and I can confirm it not longer there.
Here is the line of code that throwing the error.
If Date.Now.AddDays(LoadsFilter * -1) > Convert.ToDateTime(myReader(2)) Then
ShowLoad = 0
End If
I'm still quite new to vb so I'm not sure what to do here.
I was thinking of passing a method to read null values but I have already deleted the null value. I'm not sure how to go about this, can anyone help please?
There's no need for any conversion. The data reader has its own methods for null tests and for getting data in the appropriate type, e.g.
If Not myDataReader.IsDBNull(2) Then
Dim dt = myDataReader.GetDateTime(2)
'Use dt here.
End If
You can also use a single line to get a Nullable(Of Date):
Dim dt = If(myDataReader.IsDBNull(2), New Date?, myDataReader.GetDateTime(2))
Note that, if you prefer to use column names rather than indexes, which make your code clearer, then you can use the GetOrdinal method, as those other methods only support indexes:
Dim dt = If(myDataReader.IsDBNull(myDataReader.GetOrdinal("ColumnName")),
New Date?,
myDataReader.GetDateTime(myDataReader.GetOrdinal("ColumnName")))

Crystal Report randomly breaks when setting parameter value

I have searched high and low for a fix to this, so I apologize in advance if this is a dumb question or a repeat question.
So I have this Crystal Report, no I unfortunately do not know the version I'm on, that works most of the time and randomly breaks under the exact same conditions as when it works. On the times that it breaks, when I go to set the parameter with ApplyCurrentValue, it immediately pops up a window that asks for all parameters (as if none were set). When I press exit, it breaks with
System.NullReferenceException: Object reference not set to an instance
of an object. at
CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinition.ApplyCurrentValues(ParameterValues
currentValues)
Below is the code. Also, every parameter I pass is the correct value so none of them are null and actually have a value.
rpt.SetDataSource(ds)
crv.ReportSource = rpt
AddCrystalReportParameters("EntityName", entityName)
AddCrystalReportParameters("dtFrom", datFrom.ToShortDateString())
AddCrystalReportParameters("dtTo", datTo.ToShortDateString())
AddCrystalReportParameters("RectEntityDesc", rectEntityDesc)
Here is the method that I use.
Sub AddCrystalReportParameters(ByVal sFieldName As String, ByVal sValue As String)
Dim discreteValue As New ParameterDiscreteValue()
Dim values As New ParameterValues()
values = rpt.DataDefinition.ParameterFields(sFieldName).CurrentValues()
discreteValue.Value = sValue 'Assign parameter
values.Add(discreteValue)
rpt.DataDefinition.ParameterFields(sFieldName).ApplyCurrentValues(values)
End Sub
Because it is so random for when it breaks, it has made testing it extremely difficult. I was thinking that maybe the report isn't loaded, but I checked for rpt.IsLoaded in which it said it was even though it went on to break when it went to add the parameter.
Thanks for your help!
You do not need to set parameters if you are setting the datasource using SetDataSource
First Create Parameters in the report itself with names (EntityName,dtFrom,dtTo and RectEntityDesc) as you described. then add these parameters to your report as objects then in the code you can set the values as code below:
rpt.SetParameterValue("#EntityName", EntityName)
rpt.SetParameterValue("#dtFrom", dtFrom.SelectedDate)
rpt.SetParameterValue("#dtTo", dtTo.SelectedDate)
rpt.SetParameterValue("#RectEntityDesc", rectEntityDesc)
this code used because you have already added the parameters to the report you are only setting the value of each parameter.

linq2sql synchronized rapid udeletes

I'm having some timing problems in a unit test of some of my vb code.
I set up a test harness by checking for and then deleting records added to the db in the previous testing session, and then I test my recording adding code by adding back the same records.
Interestingly this code works fine when there is a break in the debugger, but fails with a "duplicate key" exception when I let it run with no breaks, which leads me to believe there is some kind of concurrency issue.
The basic metacode is as follows:
DoTest()
dim j as datacontext
dim recs = from myrecs in j.mythings select myrecs where myrecs.key="key1" or
myrecs.key = "key2"
if recs.count > 0
for each rec in myrecs
j.mythings.deleteonsubmit(rec)
next
j.submitchanges()
end if
j.dispose
dim tc as new tablecontroller()
tc.addrecordtomytable("key1","value1")
tc.addrecordtomytable("key2","value2")
end
Class tablecontroller
Sub addrecordstomytable(key as string, value as string)
dim j as new mydatacontext
dim thing as new mything
thing.key = key
thing.value = value
j.mythings.addonsubmit(thing)
j.submitchanges
j.dispose
end sub
end class
I've confirmed that I'm properly deleted the previous added records, and this works fine as does adding the new records when I have a break in the code before I hit the add records step. but without the break, it throws duplicate key exceptions in the "addrecordestomytable" method suggesting that it hasn't grabbed the current version of the table when it creates the new data context in addrecordstomytable, even though the records should have already been deleted.
I've tried refreshing the table, but this doesn't seem to work either.
Note backing database is ms sql server 10
Suggestions?
This is not so much an answer as a trouble-shooting technique. Have you tried using the log property? i.e.
j.log = Console.Out
So that you can see the actual SQL generated to make sure it is what you expect? Other than that is there anything relevant in your test setup or tear down? Is there anything managing a transaction? Are there triggers running? In terms of the latter if there is a trigger that takes some time to run and then the delete is finalized that might explain what you're seeing. I guess LINQ syntax varies between VB and C#, which surprised me, because I don't think your comparison code as written is valid in C#, you would need ==, not =, for a comparison but since it works when you break in the debugger...

Autocomplete list does not show all possible completions with BindingSource.Item

I've got a BindingSource for a DataSet. I'm fairly new to this whole binding business and databases, and it took me hours to figure out how to use BindingSource to get to an item, because the Row method was not included in the autocomplete. Not to confuse anyone, here's some sample code:
Dim somePreperty As String
Dim dataSet As New MyDataSet
Dim table As New MyDataSetTableAdapters.MyTableAdapter
Dim source As New BindingSource
source.DataSource = dataSet
source.DataMember = "SomeMember"
table.Fill(dataSet.SomeMember)
lablCabinet.DataBindings.Add("Text", source(0), "MemberID") '<This works fine>'
someProperty = source.Item(0).Row("ProductModel") '<So does this>'
The code runs perfectly and does exactly what I want. My problem is the following: When I've typed in source.Item(0)., autocomplete does not display Row in the list. Is this perhaps not the best way to do what I'm doing? Is there a reason it's hidden? Is this a good coding practice to do so? The fact that is wasn't there took me lots of time Googling, so I'm trying to figure out whether it's a Visual Studio glitch or my own.
Thanks in advance! = )
source.item(0) returns an object, so intellisense has no idea what is is.
You know what it should be, the compiler does not.
If you cast it first to a table or assing it to a table, intellisense will kick in.
So either:
ctype(source.item(0),datatable)
Or
dim tbl as datatable=source.item(0).