A Question About Linq To Sql - asp.net

When I write a code like below, I take this error message: "The query operator 'ElementAtOrDefault' is not supported."
How can I fix it?
Dim tmpQuestion As New UIData
Dim strViews = From t In tmpQuestion.LU_QUESTIONs _
Where t.ID_QUESTION = Request.QueryString("IdQuestion") _
Select t
Dim mtViews = strViews(0).MT_VIEWS

You haven't really queried yet.
strViews isn't the result set, it is the query. You need to actually retrieve some data.
var chosen = strViews.FirstOrDefault();

Have you tried using the FirstOrDefault() then check to make sure it is not null. My VB syntax is probably suspect, but you get the idea.
Dim strView = (From t In tmpQuestion.LU_QUESTIONS _
Where t.ID_QUESTION = Request.QueryString("IdQuestion") _
Select t).FirstOrDefault()
Dim mtViews as ...
If Not strView Is Nothing
mtViews = strView.MT_VIEWS
EndIf

I am no expert in VB or LINQ2SQL but does this not have anything to do with the fact that you say strViews(0).MT_VIEWS while there is a chance that strViews can be null?

Related

ms_access Run time error 3078 in VBA although query runs as saved query [duplicate]

I have a query called qryAlloc_Source that has two paramaters under one criteria:
>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
A have a separate query that ultimately references qryAlloc_Source (there are a couple queries in between), and that query runs fine when I double click it in the UI, but if I try to open it in VBA, I get an error. My code is:
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
I am getting run-time error 3061, Too few parameters. Expected 2. I've read that I may need to build out the SQL in VBA using the form parameters, but it would be pretty complex SQL given that there are a few queries in the chain.
Any suggestions as to a workaround? I considered using VBA to create a table from the query and then just referencing that table--I hate to make extra steps though.
The reason you get the error when you just try to open the recordset is that your form is not open and when you try to access [forms]![frmReportingMain] it's null then you try to get a property on that null reference and things blow up. The OpenRecordset function has no way of poping up a dialog box to prompt for user inputs like the UI does if it gets this error.
You can change your query to use parameters that are not bound to a form
yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
Then you can use this function to get the recordset of that query.
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim db As DAO.Database
Dim qdef As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs("qryAlloc_Debits")
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
The disadvantage to this is that when you call this now on a form that is bound to it it doesn't dynamically 'fill in the blanks' for you.
In that case you can bind forms qryAlloc_debts and have no where clause on the saved query, then use the forms Filter to make your where clause. In that instance you can use your where clause exactly how you have it written.
Then if you want to still open a recordset you can do it like this
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim qdef As DAO.QueryDef
Set qdef = New DAO.QueryDef
qdef.SQL = "Select * from qryAlloc_Debits where AllocStart >= pAllocStart and pAllocEnd <= pAllocEnd"
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
While a [Forms]!... reference does default to a form reference when a QueryDef is run from the GUI, it is actually just another Parameter in the query in VBA. The upshot is you don't have to recode your query/create a new one at all. Also, as #Brad mentioned, whether a parameter is in the final query of a chain of queries or not, you are able to refer to the parameter as if it is in the collection of the final query. That being the case, you should be able to use code similar to this:
Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryAlloc_Debit")
If CurrentProject.AllForms("frmReportingMain").IsLoaded Then
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart]
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd]
Else
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart)
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd)
End If
Set rst = qdf.OpenRecordset
Do Until rst.EOF
'...do stuff here.
Loop
Set rst = Nothing
Set qdf = Nothing
Set db = Nothing
End Function
If the referenced form is open, the code is smart enough to use the referenced controls on the form. If not, it will use the dates supplied to the subroutine as parameters. A gotcha here is that the parameters did not like when I set them as date types (#xx/xx/xx#), even if the field were dates. It only seemed to work properly if I set the params as strings. It didn't seem to be an issue when pulling the values straight out of the controls on the forms, though.
I know it's been a while since this was posted, but I'd like to throw in my tuppence worth as I'm always searching this problem:
A stored query can be resolved:
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
For SQL:
Set db = CurrentDb
Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " & _
"WHERE ID = " & Me.lstID & _
" AND dWeekCommencing = " & CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) & _
" AND DB_Status = 'Used'")
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
This assumes that all parameter values are accessible - i.e. forms are open and controls have values.
'I have two parameters in my recordset and I was getting the "Too few parameters. Expected 2" 'error when using an OpenRecordset in MS Access vba, and this is how I got around it and IT WORKS! see the below sub routine:
'Private Sub DisplayID_Click()
'1. I created variables for my two parameter fields xEventID and xExID as seen below:
Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer
Dim xExId As Integer
'2. Sets the variables to the parameter fields as seen below:
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
'3. Set the rst to OpenRecordSet and assign the Set the variables to the WHERE clause. Be sure to include all quotations, ampersand, and spaces exactly the way it is displayed. Otherwise the code will break!exactly as it is seen below:
Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _
& "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _
& "WHERE (((tblInfo_Exhibitor.EventID) =" & xEventID & " ) and ((tblInfo_Exhibitor.ExID) =" & xExId & " ));")
rst.Close
Set rst = Nothing
db.Close
'End Sub

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

How do I correctly check DBNull in VB?

Why does the following code:
A = not IsDBNull(CurRow("BuyBook")) AndAlso CType(CurRow("BuyBook"), string) = "Yes"
results in the following error:
Conversion from type 'DBNull' to type 'String' is not valid.
When AndAlso is supposed to short-circuit according to this article:
http://support.microsoft.com/kb/817250
You are correct. AndAlso is short circuiting.
However, the error comes by calling CurRow("GuyBook") (verify this in a debugger to make sure I'm not a liar or making some crazy assumptions or just misremembering* ;-). Before you ask for a value, you need to ask the DataRow if it has a value. That is, use:
CurRow.IsNull("BuyBook")
Happy coding.
*One should just be able to compare with DBNull.Value or use IsDBNull. However, I am fairly certain that I ran into a row before that threw these exceptions instead of returning a DBNull object. Start by finding out -- in the Immediate Window of the Debugger -- exactly which expression throws the exception.
Have you tried comparing like this:
If CurRow("BuyBook") Is DBNull.Value Then
'...
End If
Instead of not IsDBNull(CurRow("BuyBook")), use NOT (CurRow("BuyBook")) is System.Dbnull.Value). Try this:
A = (NOT (CurRow("BuyBook")) is System.Dbnull.Value) AndAlso CType(CurRow("BuyBook"), string) = "Yes"
OR
A = not string.IsNullOrEmpty(CurRow("BuyBook")) AndAlso CType(CurRow("BuyBook"), string) = "Yes"
If dt.Rows(0)("BuyBook") = DBNull.Value Then
End If
Hope it helps.
In vb.net I usually do something like this:
A = (CurRow("BuyBook") & "" = "Yes")
Old trick from vb6 era. If CurRow("BuyBook") is null, vb.net will consider it as empty string when concatenating it with another string.

Linq to Sql convert to generic list in VB.NET

I am trying to learn some VB.NET for my coo-op that starts next week, and for that reason i took my portfolio web site that is on C# and just started to converting it to VB.NET to get familiar with the syntax.
I am sure my problem is simple however i have a hard time solving it.
I am trying to grab data with the linq query and then return it as list to bind to the Repeater.
I have the following function:
Public Function getProjects() As List(Of portfolio_website)
Using myPortfolio As New PortfolioDataContext
Try
Dim myProjects = (From p In myPortfolio.portfolio_websites _
Order By p.website_id Descending _
Select New With {.name = p.website_name, .id = p.website_id}).Take(5)
Return myProjects
Catch ex As Exception
Return Nothing
End Try
End Using
End Function
However I am getting an error.
If i would do it in C# then myProjects will be var and in return i will have
return myProjects.ToList();
And it would work fine. However if I try to use ToList() in VB.NET i am getting error that it cannot convert it from ling to sql List to the generic list.
How do i do this convertion in VB.NET ? or maybe there is another way ?
I am decent when it comes to C# however somewhat lost with the VB.NET syntax.
I hate it.
Second after I asked my question i realized my mystake.
It is same as in C#, but if i take
Select New With {.name = p.website_name, .id = p.website_id
then i either need to have a custom object, or i need to take everything.
So i changed my linq to sql to the
Dim myProjects = (From p In myPortfolio.portfolio_websites _
Order By p.website_id Descending _
Select p).Take(5)
Return myProjects.ToList()
and now everything is working.

ADO error "Current Recordset does not support updating. This may be a limitation of the provider, or of the selected locktype."

I am doing some calculation with the data set I take from my database. Null values give errors so I tried replacing null values with zeros(0). Here is the error I get,
ADODB.Recordset error '800a0cb3'
Current Recordset does not support
updating. This may be a limitation of
the provider, or of the selected
locktype.
Never seen it before. Here is my code.
If IsNull(objRevenueToday("REVENUE")) Then
objRevenueToday("REVENUE") = 0
End If
Your recordset appears to be read-only. There could be a number of reasons for this; you're reading a view that contains a Group By clause, you don't have permissions, etc.
Using the syntax Set Recordset = Command.Execute always opens a read only cursor. What you need to do is open the cursor using the Recordset object. The Source parameter of the Open method is your Command object. This allows you to set the desired location and locktype.
Dim cmdProc as ADODB.Command
Dim rsData as ADODB.Recordset
Set cmdProc = New ADODB.Command
With cmdProc
Set .ActiveConnection = SomeConnection
.CommandType = adCmdStoredProc
.CommandText = "selCustomer"
' ... Create parameters
End With
Set rsData as New ADODB.Recordset
rsData.Open cmdProc,, adOpenStatic,adLockBatchOptimistic
'...Process recordset data.
Here is the solution:
If IsNull(objRevenueToday("REVENUE")) Then
RevenueToday = "0"
Else
RevenueToday = objRevenueToday("REVENUE")
End If
Not very ideal but fixed my error.
Assuming SQL Server (although similar techniques available in other DBs.
Change the query so that is will not return nulls in records. For example in the T-SQL
SELECT ISNULL(REVENUE, 0), .... FROM ....
Change the settings as below. It force the client side cursor...It worked for me
set pagedlistrs=CreateObject("adodb.recordset")
pagedlistrs.cursorlocation = 3 ' adUseClientpagedlistrs
pagedlistrs.Open SQL, objConn, 3,3,1

Resources