Retrieving data from Access 2010 view with VB.NET 2008 throws error - vb.net

I'm trying to learn VB.NET and I'm looking to retrieve data from an Access 2010 view, using Vb.NET 2008, problem is I'm getting the following error. System.ArgumentNullException was unhandled Message=Value cannot be null
I cannot work out how to solve the error, so hopefully someone with more experience can help.
Public Function GetMyoleDataAdapterStudentQuestionRepeat(ByRef mydataSet As DataSet, ByVal topicId As String, ByVal groupId As String) As OleDbDataAdapter
Try
Dim strAccessConn As String = _appConfigDbConn
Dim cn As OleDbConnection = New OleDbConnection(strAccessConn)
Dim ds As New DataSet
Dim da As New OleDbDataAdapter("qryStudentNameRandomBasedOnScore", cn)
da.SelectCommand.CommandType = CommandType.StoredProcedure
da.SelectCommand.Parameters.AddWithValue("#GroupID", groupId)
da.Fill(ds, "Student")
Return da
Catch ex As Exception
Throw New ApplicationException(ex.InnerException.Message.ToString())
End Try
End Function
Within button click
Dim myoleDataAdapter As OleDbDataAdapter = GroupData.GetMyoleDataAdapterStudentQuestionRepeat(mydataSet, topicId, groupId)
myoleDataAdapter.Fill(mydataSet)
txtStudentName.DataBindings.Add("Text", mydataSet.Tables(0), "studentname")
This line throws error: myoleDataAdapter.Fill(mydataSet)
And in case it helps, my view is
SELECT TOP 1 tblStudentNameAndScore.studentname
FROM tblStudentNameAndScore
WHERE (((tblStudentNameAndScore.[QuizCount]) Between 2 And 10)) AND tblStudentNameAndScore.GroupID = ?
ORDER BY Rnd(QuizCount);
Thanks for any hep

In this line
myoleDataAdapter.Fill(mydataSet)
you try to fill the dataset but this dataset is never initialized.
Following your actual pattern, you should change your code that initialize the dataadapter in this way
Public Function GetMyoleDataAdapterStudentQuestionRepeat(ByVal topicId As String, ByVal groupId As String) As OleDbDataAdapter
Try
Dim strAccessConn As String = _appConfigDbConn
Dim cn As OleDbConnection = New OleDbConnection(strAccessConn)
Dim ds As New DataSet
Dim da As New OleDbDataAdapter("qryStudentNameRandomBasedOnScore", cn)
da.SelectCommand.CommandType = CommandType.StoredProcedure
da.SelectCommand.Parameters.AddWithValue("#GroupID", groupId)
Return da
Catch ex As Exception
Throw New ApplicationException(ex.InnerException.Message.ToString())
End Try
End Function
and then in the caller code write
Dim myoleDataAdapter As OleDbDataAdapter = GroupData.GetMyoleDataAdapterStudentQuestionRepeat( topicId, groupId)
mydataSet = new DataSet()
myoleDataAdapter.Fill(mydataSet)
....
In the method that returns the adapter you don't need to pass the dataset because you don't use it in any way and there is no need to create and fill another dataset. Just return the adapter and work on the caller code
Of course you could also change the method and return a dataset filled with your data instead of the DataAdapter. Probably this solution could be considered more encapsulated
Public Function GetStudentQuestionRepeat(ByVal topicId As String, ByVal groupId As String) _
As Dataset
....
Dim da As New OleDbDataAdapter("qryStudentNameRandomBasedOnScore", cn)
da.SelectCommand.CommandType = CommandType.StoredProcedure
da.SelectCommand.Parameters.AddWithValue("#GroupID", groupId)
Dim ds = new Dataset()
da.Fill(ds, "Student")
Return ds
....
End Function
By the way, what is the purpose of topidID variable passed and never used?

Why not return a Dataset instead of DataAdapter, like:
Public Function GetMyoleDataAdapterStudentQuestionRepeat(ByVal topicId As String, ByVal groupId As String) As DataSet
Try
Dim strAccessConn As String = _appConfigDbConn
Dim cn As OleDbConnection = New OleDbConnection(strAccessConn)
Dim ds As New DataSet
Dim da As New OleDbDataAdapter("qryStudentNameRandomBasedOnScore", cn)
da.SelectCommand.CommandType = CommandType.StoredProcedure
da.SelectCommand.Parameters.AddWithValue("#GroupID", groupId)
da.Fill(ds, "Student")
Return ds
Catch ex As Exception
Throw New ApplicationException(ex.InnerException.Message.ToString())
End Try
End Function
And then when you call it would be shorter:
Dim myDataSet As DataSet = GroupData.GetMyoleDataAdapterStudentQuestionRepeat(topicId, groupId)
txtStudentName.DataBindings.Add("Text", myDataSet.Tables(0), "studentname")

Related

Web service code to add SQL string connection and string query manually?

I'm using the Web service as given below for getting the data from database. In that code it has static string connection and string query. I'm using the same web service for multiple functions. Instead of using the same function I need to give the string query and string connection manually to avoid multiple of using the same code. Is it possible to give the string connection and string query in run time.
Here is the code.
<WebMethod()> _
Public Function GetData() As String
Dim sqlcon As New SqlClient.SqlConnection
Dim sqlcmd, cmd As SqlClient.SqlCommand
Dim objeDS, objeDS1 As DataSet
Dim adpp, adpp1 As SqlClient.SqlDataAdapter
Dim dt, dt1 As DataTable
Dim pack_tbl As New DataTable
sqlcon.ConnectionString = ConfigurationManager.AppSettings("constr")
sqlcon.Open()
sqlcmd = New SqlClient.SqlCommand()
sqlcmd.Connection = sqlcon
sqlcmd.CommandType = CommandType.Text
sqlcmd.CommandText = "sqlcommand"
objeDS = New DataSet()
adpp = New SqlClient.SqlDataAdapter()
adpp.SelectCommand = sqlcmd
adpp.Fill(objeDS)
sqlcon.Close()
dt = New DataTable()
dt = objeDS.Tables(0)
Return objeDS.GetXml()
'Return "Welcome"
End Function
Try this code this helps you.
VB code
<WebMethod()> _
Public Function GetData(ByVal strQuery As String, ByVal strCon As String) As String
Dim dt As New DataTable()
dt.Clear()
Using conn As New System.Data.SqlClient.SqlConnection()
conn.ConnectionString = ConfigurationManager.ConnectionStrings(strCon).ConnectionString
Using cmd As New System.Data.SqlClient.SqlCommand()
cmd.CommandText = strQuery
cmd.Connection = conn
conn.Open()
Dim da As New SqlDataAdapter(cmd)
da.Fill(dt)
Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer()
Dim rows As New List(Of Dictionary(Of String, Object))()
Dim row As Dictionary(Of String, Object)
For Each dr As DataRow In dt.Rows
row = New Dictionary(Of String, Object)()
For Each col As DataColumn In dt.Columns
row.Add(col.ColumnName, dr(col))
Next
rows.Add(row)
Next
Return serializer.Serialize(rows)
End Using
End Using
End Function

how can i use parameters to avoid sql attacks

I have a project without any parameters used in SQL queries.
Is there any solution so that i don't have to change the function and validate parameters from the Query string itself?
Query = "select * from tbl_Users where userName='"& textbox1.text &"' and password='"& textbox2.text &"' "
ds = obj.ExecuteQueryReturnDS(Query)
Function where query is passed:
Public Function ExecuteQueryReturnDS(ByVal stQuery As String) As DataSet
Try
Dim ds As New DataSet
Using sqlCon As New SqlConnection(connStr)
Dim sqlCmd As New SqlCommand(stQuery, sqlCon)
Dim sqlAda As New SqlDataAdapter(sqlCmd)
sqlCmd.CommandType = CommandType.Text
sqlAda.Fill(ds)
End Using
Return ds
Catch ex As Exception
End Try
End Function
I tried passing parameters into the function but the function is used in for other queries as well hence i cannot define the parameters inside the function .
Is there any work around
I think the only solution is create a new function and gradually migrate to it.
Public Function ExecuteQueryReturnDS(ByVal cmdQuery As SqlCommand) As DataSet
Try
Dim ds As New DataSet
Using sqlCon As New SqlConnection(connStr)
cmdQuery.Connection = sqlCon
Dim sqlAda As New SqlDataAdapter(cmdQuery)
sqlAda.Fill(ds)
End Using
Return ds
Catch ex As Exception
End Try
End Function
cmdQuery is intended to be an SqlCommand to which you already added all the parameters you need.
As an intermediate step before switching to a full parameterized application you could change your actual method to be able to receive an optional argument.
This optional argument will be your SqlParameter array defined in the point where you call this query
Public Function ExecuteQueryReturnDS(ByVal stQuery As String, Optional ByVal prms As SqlParameter() = Nothing) As DataSet
Try
Dim ds As New DataSet
Using sqlCon As New SqlConnection(connStr)
Dim sqlCmd As New SqlCommand(stQuery, sqlCon)
if Not prms Is Nothing Then
sqlCmd.Parameters.AddRange(prms)
End if
Dim sqlAda As New SqlDataAdapter(sqlCmd)
sqlCmd.CommandType = CommandType.Text
sqlAda.Fill(ds)
End Using
Return ds
Catch ex As Exception
End Try
End Function

Joining many-to-many DataTables in VB.Net

I have 2 data sources from different source types, like:
Dim connSql As String = "Data Source=sql_src;Initial Catalog=my_db;Persist Security Info=True;User ID=usr;Password=pwd;"
Dim connOle As String = "Provider=IBMDA400;Data source=src;User Id=usr;Password=pwd"
dim qrySql as String = "Select uniqueID, name From tblSql"
dim qryOle as String = "Select name, ID From tblOle"
I place them into DataTables using functions like this (mostly for reference):
Public Shared Function sqlQryDT(qry As String, conn As String) As DataTable
Dim dt As New DataTable
Dim sqlconn As New SqlClient.SqlConnection(conn)
sqlconn.Open()
Dim adapter As New SqlClient.SqlDataAdapter(qry, sqlconn)
Try
adapter.Fill(dt)
Catch ex As Exception
Finally
sqlconn.Close()
End Try
Return dt
End Function
Public Shared Function oleQryDT(qry As String, conn As String) As DataTable
Dim dt As New DataTable
Dim cn As New OleDb.OleDbConnection(conn)
Dim cmd As New OleDb.OleDbCommand("", cn)
Dim da As New OleDb.OleDbDataAdapter(cmd)
cmd.CommandText = qry
Try
cn.Open()
da.Fill(dt)
Catch ex As Exception
Finally
cn.Close()
End Try
Return dt
End Function
Dim dtSql as DataTable = sqlQryDT(qrySql, connSQL)
Dim dtOle as DataTable = oleQryDT(qryOle , connOle)
My goal is to have a DataTable consisting of uniqueID,name,ID
(Edit) If I could do an SQL query it would look like SELECT * FROM dtSql JOIN dtOle ON dtSql.name = dtOle.name
I have tried using a DataRelation by placing the tables into a DataSet and adding a relationship on name, but since names may not be unique, this fails.
I have also tried using LINQ, but that always returns IEnumerable(System.Collections.Generic) and I can't find an easy way to place the contents into a DataTable, except by iterating through every item. And, the code is messy when there are a large number of columns.
I feel like there should be a way to do this without using a For Each loop
I looked at these question, but they didn't fully help me.
How to inner join two already filled DataTables in VB.NET
Merging 2 data tables in vb.net

get single value from sql-query into a textbox

The result of my sql-query is a single value i want display that in a lable but dont know how. I have a solution creating a dataset put the result of the query into that dataset and get it by row(0),column(0) but i guess there is a smarter way doing it.
Private myquery As String
Sub New(ByVal query As String)
myquery = query
End Sub
Public Sub query_Send()
Dim myconn As New SqlConnection("Data Source=DB;Integrated Security=TRUE")
Dim mycmd As SqlCommand = New SqlCommand(Me.myQuery, myconn)
Dim myTable As New DataTable
Dim previousConnectionState As ConnectionState = myconn.State
Try
If myconn.State = ConnectionState.Closed Then
myconn.Open()
Dim myDA As New SqlDataAdapter(mycmd)
myDA.Fill(myTable)
tb.text = **...**
End If
If previousConnectionState = ConnectionState.Closed Then
myconn.Close()
End If
End Try
End Sub
You can use SqlCommand.ExecuteScalar Method
Dim querystr as String = "select value from MyTable where ID=5"
Dim mycmd As New SqlCommand(querystr, connection)
dim value as Object = mycmd.ExecuteScalar()
The value you can put to your textbox. ExecuteScalar returns first value of first row of the resultset (equivalent of row(0).column(0) ) When no record is returned the value is nothing.
Try something more along the lines of:
Using myconn As New SqlConnection("Data Source=DB;Integrated Security=TRUE")
Dim myDA As New SqlDataAdapter()
myDA.SelectCommand = New SqlCommand(myQuery, myconn)
myDA.Fill(myTable)
Return myTable
End Using
Or you can just get ahold of the first item in the first row with
myTable.Rows(0).ItemArray(0).ToString()

Why can't I return a Dataset from a function inside a VB.net class?

I am using WinForms and trying to retrieve all the data from the database once on form Load so I won't have to go back and forth to the database a lot.
I created a class and wrote a function that returns a dataset but I'm not being able to refer to it from my forms.
This is the code:
Private Function FillKeywords() As DataSet
Dim ds1 As DataSet : Dim cmd as SqlCommand
Dim da As SqlDataAdapter
Try
cmd = New SqlCommand("Dbo.selectkeywords", cn)
cmd.CommandType = CommandType.StoredProcedure
da = New SqlDataAdapter(cmd)
ds1 = New DataSet
da.Fill(ds1, "Keywords")
Return ds1
Catch ex As SqlClient.SqlException
WriteExToFile(ex.ToString)
Catch ex As Exception
WriteExToFile(ex.ToString)
End Try
End Function
I'll take a wild guess and say you will need to lose the Private keyword if you want your function to be accessible from another class or module.