Comparing object with Nothing in vb.net - asp.net

I have a code
Dim drQues As DataRow = dtQuestion.AsEnumerable()
.First(Function(uqno) uqno.Field(Of Int32)("uniqueqno") = drqno("uniqueqno"))
I want to check if drQues is Nothing
I tried
If Not drQues <> Nothing THEN
but it says
<> is not defined for System.Data.DataRow and System.Data.DataRow
how can I check if there was a row for specified condition in linq?

Use Is or IsNot where the usual comparison operators are not defined.
If drQues Is Nothing Then

Related

VB.net Null reference on database connection

I know I'm being an idiot here and I just can't work it out. But i'm trying to take some data back from a vb.net database. It's falling over with a Object reference not set to an instance of an object error. And before the code runs it's saying the variable is being used before it's set, but I can't see how. Code:
Private taNotifications As dsDataTableAdapters.NotificationsTableAdapter = New dsDataTableAdapters.NotificationsTableAdapter
Dim notification As dsData.NotificationsDataTable = taNotifications.GetDataByClientID(userrow.UserID)
If notification.Rows.Count > 0 Then
Dim notificationrow As dsData.NotificationsRow
Dim forwardURL As String = notificationrow.ForwardLocation
End If
It falls over on the Dim forwardURL As String = notificationrow.ForwardLocation
The problem is that you have never instantiated the notificationRow inside the if statement. You've declared it, but it doesn't belong to anything. You need to make an assignment or loop through your rows before doing anything with this object:
Dim notificationrow As dsData.NotificationsRow ' this is not instantiated
Dim forwardURL As String = notificationrow.ForwardLocation
What you really want in this case is:
For Each notificationRow As dsData.NotificationRow In notification
Dim forwardURL As String = notificationRow.ForwardLocation
' Do Something
Next
If you only HAVE one row and you know you only have 1 or 0 rows then you could use your if statement by doing:
If notification.Rows.Count > 0 Then
Dim notificationrow As dsData.NotificationsRow = _
CType(notification.Rows(0), dsData.NotificationsRow)
Dim forwardURL As String = notificationrow.ForwardLocation
End If
Edit: In the code above, I originally just had notification.Rows(0). This will produce a DataRow object, but it will not be strongly typed. You need to perform the CType that I added in order to use the custom property ForwardLocation.
You never set notificationrow to anything. Did you mean to set it like this?
Dim notificationrow As dsData.NotificationsRow = CType(notification.Rows(0), dsData.NotificationsRow)

Inserting null values into date fields?

I have a FormView where I pull data from one table (MS Access), and then insert it (plus more data) into another table. I'm having issues with the dates.
The first table has two date fields: date_submitted and date_updated. In some records, date_updated is blank. This causes me to get a data mismatch error when attempting to insert into the second table.
It might be because I'm databinding the date_updated field from the first table into a HiddenField on the FormView. It then takes the value from the HiddenField and attempts to insert it into the second table:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
myDateRequestUpdated = hfDateRequestUpdated.Value
'... It then attempts to insert myDateRequestUpdated into the database.
It works when there is a value there, but apparently you can't insert nothing into a date/time field in Access. I suppose I could make a second insert statement that does not insert into date_updated (to use when there is no value indate_updated), but is that the only way to do it? Seems like there should be an easier/less redundant way.
EDIT:
Okay. So I've tried inserting SqlDateTime.Null, Nothing, and DBNull.Value. SqlDateTime.Null results in the value 1/1/1900 being inserted into the database. "Nothing" causes it to insert 1/1/2001. And if I try to use DBNull.Value, it tells me that it cannot be converted to a string, so maybe I didn't do something quite right there. At any rate, I was hoping that if there was nothing to insert that the field in Access would remain blank, but it seems that it has to fill it with something...
EDIT:
I got DBNull.Value to work, and it does insert a completely blank value. So this is my final working code:
Dim hfDateRequestUpdated As HiddenField = FormView1.FindControl("hfDateRequestUpdated")
Dim myDateRequestUpdated = Nothing
If hfDateRequestUpdated.Value = Nothing Then
myDateRequestUpdated = DBNull.Value
Else
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value)
End If
Thanks everyone!
Sara, have you tried casting the date/time before you update it? The data mismatch error likely comes from the fact that the hfDateRequestUpdated.Value you're trying to insert into the database doesn't match the column type.
Try stepping through your code and seeing what the type of that value is. If you find that it's a string (which it seems it might be, since it's coming from a field on a form), then you will need a check first to see if that field is the empty string (VBNullString). If so, you will want to change the value you're inserting into the database to DBNull, which you can get in VB.Net using DBNull.Value.
We can't see your code, so we don't know exactly how you get the value into the database, but it would look something like this
If theDateValueBeingInserted is Nothing Then
theDateValueBeingInserted = DBNull.Value
EndIf
Keep in mind that the above test only works if the value you get from the HiddenField is a string, which I believe it is according to the documentation. That's probably where all this trouble you're having is coming from. You're implicitly converting your date/time values to a string (which is easy), but implicitly converting them back isn't so easy, especially if the initial value was a DBNull
aside
I think what Marshall was trying to suggest was the equivalent of the above code, but in a shortcut expression called the 'ternary operator', which looks like this in VB.Net:
newValue = IF(oldValue is Nothing ? DBNull.Value : oldValue)
I wouldn't recommend it though, since it's confusing to new programmers, and the syntax changed in 2008 from IFF(condition ? trueResult : falseResult)
Your code
Dim myDateRequestUpdated As DateTime
myDateRequestUpdated = DateTime.Parse(hfDateRequestUpdated.Value) : DBNull.Value()
has a couple of problems:
When you declare myDateRequestUpdated to be DateTime, you can't put a DbNull.Value in it.
I'm not sure you need the () for DbNull.Value: it's a property, not a method (I don't know enough VB to say for sure)
VB doesn't know that : operator
What you probably want is a Nullable(Of DateTime) to store a DateTime value that can also be missing.
Then use something like this to store the value:
myDateRequestUpdated = If(String.IsNullOrWhiteSpace(hfDateRequestUpdated.Value),
Nothing, DateTime.Parse(hfDateRequestUpdated.Value))
If hfDateRequestUpdated.Value is empty, then use Nothing as the result; else parse the value as date (which might fail if it is not a valid date!).
Try this:
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim str As String
If TextBox1.Text.Length <> 0 Then
str = "'" & TextBox1.Text & "'"
Else
str = "NULL"
End If
sql = "insert into test(test1) values(" & str & ")"
dsave_sql(sql)
End Sub
Function save_sql(ByVal strsql As String, Optional ByVal msg As String = "Record Saved Sucessfully") As String
Dim sqlcon As New SqlConnection(strConn)
Dim comm As New SqlCommand(strsql, sqlcon)
Dim i As Integer
Try
sqlcon.Open()
i = CType(comm.ExecuteScalar(), Integer)
save_sql = msg
Catch ex As Exception
save_sql = ex.Message
End Try
sqlcon.Close()
Return i
End Function

checking for duplicate values before attempting insert (ASP.NET)

I have a form where two fields on the first page of the form make up the primary key. I want to check for duplicate values before attempting to insert the record, since I don't want the user to go all the way through the form only to find out they can't submit it. So I'm trying to check for duplicate values when the user tries to go to the next page of the form. I wasn't quite sure how to do it, and sure enough I'm getting an error. ("Object reference not set to an instance of an object.") The problem is apparently in my if statement, "If myValue.Length > 0 Then", but I'm not sure what needs to be in place of that.
Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
'get values
Dim checkPrefix = txtCoursePrefix.Text
Dim checkNum = txtCourseNum.Text
'db connectivity
Dim myConn As New OleDbConnection
myConn.ConnectionString = AccessDataSource1.ConnectionString
myConn.Open()
'select records
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix='checkPrefix' AND course_number='checkNum'", myConn)
'execute(Command)
Dim myValue As String = mySelect.ExecuteScalar()
'check if record exists
If myValue.Length > 0 Then
CustomValidator1.ErrorMessage = "some exp text"
CustomValidator1.SetFocusOnError = "true"
CustomValidator1.IsValid = "false"
End If
End Sub
Thought I'd post the final solution:
'select records
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
'execute(Command)
Dim myValue = mySelect.ExecuteScalar()
'check if record exists
If myValue IsNot Nothing Then
CustomValidator1.SetFocusOnError = True
args.IsValid = False
End If
This error indicates that the content of myValue variable is null. If it's null you can't use Length property (or any other property for that matter) on it. You have to check for null explicitly:
If myValue IsNot Nothing Then
EDIT 1
Your sql query is wrong. I don't know what would be the right query, as I don't know your database, but I think you intender to write this:
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix=" + checfkPreix + " AND course_number=" + checkNum, myConn)
or something to that effect. You might want to consider using string.Format function for forming the string. And you also need to make sure that there is some kind of protection against SQL Injection, since you form your query from user input. In your case using of OleDbParameter might be appropriate.
Edit 2
You also right to mention that there might be a problem with ExecuteScalar. ExecuteScalar is supposed to return a single value and your select query are returning two (prefix and course_number). Change it so that it returns a single parameter SELECT prefix FROM or simply SELECT 1 FROM and then the rest of the query:
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
Edit 3
You are not setting failed validation properly in your validator.
Add
args.IsValid = False
inside your if statement.
First ExecuteScalar will only return a single value, so in this case you are only going to get the column prefix from the result. Second if there is no match with your query it will return null, so your next length check should account for that scenario:
if String.IsNullOrEmpty(myValue) Then
...
Reference: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
myValue is null if there is no duplicate, so you have to apply .Length only if myValue is not null (which means checking for null only is enough; without .Length)
If Not string.IsNullOrEmpty(myValue) Then
try something like this instead (you will have to adapt it to VB.Net) DBNull is different from Null or Nothing so you have to compare it to both
If myValue <> DBNull and not myvalue is nothing Then

Programatic referencing of literals and object properties

I have advice that this might work for programmatically filling a set of literals from a set of object properties:-
For i As Integer = 1 To noOfTexts
Dim ctl As Literal = DirectCast(FindControl("help" & i), Literal)
If ctl IsNot Nothing Then
ctl.Text = pageData.help(i).trim()
ctl.Visible = True
End If
Next
However, the line: ctl.Text = pageData.help(i).trim() fails because it's not understood that pageData.help(i) should translate to pageData.help1, pageData.help2, etc.
Is there some syntax that would achieve this in VS2010 Asp.net VB?
You can reference properties dynamically using reflection...
Dim PageDataType As Type = GetType(pageData)
Dim PropertyName As String = "help" & i
Dim Property As PropertyInfo = PageDataType.GetProperty(PropertyName)
Dim PropertyValue As String
If Property IsNot Nothing
PropertyValue = Property.GetValue(pageData, Nothing)
End If
Note: Reflection in .NET is slower than direct access, but not enough to make its use impractical

compare data in a vb.net dataset with values in an array list

I'm looking for an efficient way of searching through a dataset to see if an item exists. I have an arraylist of ~6000 items and I need to determine which of those doesn't exist in the dataset by comparing each item within the arraylist with data in a particular column of the dataset.
I attempted to loop through each item in the dataset for each in the arraylist but that took forever. I then attempted to use the RowFilter method below. None of which looks to be efficient. Any help is greatly appreciated, as you can tell I'm not much of a programmer...
example:
Dim alLDAPUsers As ArrayList
alLDAPUsers = clsLDAP.selectAllStudents
Dim curStu, maxStu As Integer
maxStu = alLDAPUsers.Count
For curStu = 0 To maxStu - 1
Dim DomainUsername As String = ""
DomainUsername = alLDAPUsers.Item(curStu).ToString
Dim filteredView As DataView
filteredView = dsAllStudents.Tables(0).DefaultView
filteredView.RowFilter = ""
filteredView.RowFilter = "szvausr_un = '" & DomainUsername & "'"
Dim returnedrows As Integer = filteredView.Count
If returnedrows = 0 Then
'' Delete the user...
End If
Next
You can get better performance by Sorting the list and ordering the dataset. Then you can walk them together, matching as you go. This is especially true since you are probably already ordering the dataset at least (or, you should be) in the sql query that creates it, making that step essentially free.
You should consider using a generic list rather than an ArrayList, and some other stylistic points on your existing code:
Dim LDAPUsers As List(Of String) = clsLDAP.selectAllStudents
For Each DomainUsername As String in LDAPUsers
Dim filteredView As DataView = dsAllStudents.Tables(0).DefaultView
filteredView.RowFilter = "szvausr_un = '" & DomainUsername & "'"
If filteredView.Count = 0 Then
'' Delete the user...
End If
Next
This does the same thing as your original snippet, but in half the space so it's much cleaner and more readable.
Try switching your array list to Generics. From what I understand they are much faster than an array list.
Here is a previous SO on Generics vs Array List
If you use generics as suggested, you can have two Lists of string and do the following:
for each s as string in LDAPUsers.Except(AllStudents)
''Delete the user (s)
next
Where LDAPUsers and AllStudents are both List(Of String)
Edit:
You can also change the except to:
LDAPUsers.Except(AllStudents, StringComparer.InvariantCultureIgnoreCase)
to ignore case etc.
Edit 2:
To get the generic lists could be as simple as:
Dim LDAPUsers as new List(Of String)(alLDAPUsers.Cast(Of String))
Dim AllStudents as new List(OfString)()
for each dr as DataRow in dsAllStudents.Tables(0).Rows
AllStudents.Add(dr("szvausr_un"))
next
Or you can go with the Linq-y goodness as Joel mentions, but my exposure to that is limited, unfortunately...
Like others have said, generics or linq would be better options. However, I wanted to point out that you don't need to use a DataView. The datatable has a Select method...
dsAllStudents.Tables(0).Select("szvausr_un = '" & DomainUserName & "'")
It returns an array of DataRows. I'm sure it will perform just as poorly as the view but I think it's a little cleaner.
Get the Dim statements out of the loop.... Your performance is suffering from repeated variable instantiation and reallocation.
Also remove any statements you dont need (rowfilter = "")
Dim alLDAPUsers As ArrayList
Dim DomainUsername As String
Dim curStu, maxStu As Integer
Dim filteredView As DataView
Dim returnedrows As Integer
alLDAPUsers = clsLDAP.selectAllStudents
maxStu = alLDAPUsers.Count
For curStu = 0 To maxStu - 1
DomainUsername = alLDAPUsers.Item(curStu).ToString
filteredView = dsAllStudents.Tables(0).DefaultView
filteredView.RowFilter = "szvausr_un = '" & DomainUsername & "'"
returnedrows = filteredView.Count
If returnedrows = 0 Then
'' Delete the user...
End If
Next

Resources