Insert VB.net Data Table into a Visual Foxpro table - vb.net

My company wants to slowly switch over some old programs that are written in Visual FoxPro 6.0. The problem is that we have a bunch of programs that still reference FoxPro tables.
I have a query that pulls information down to a data table in vb.net. What do I need to do to insert the information from the data table into a FoxPro table.
This is the initial query that get's put into a data table.
Dim SConn As New OleDbConnection(conn)
Dim da As OleDbDataAdapter
Dim dt As New DataTable
Dim sSql As String = "SELECT DISTINCT * FROM DWEmployee where cono <> 'XX' AND officeno <> 'XX' AND cono <> '' AND officeno <> ''"
SConn.Open()
da = New OleDbDataAdapter(sSql, SConn)
da.SelectCommand.CommandTimeout = 90
da.Fill(dt)
SConn.Close()
What do I need to do to replicate this Foxpro code in VB.net
select distinct * from (the data table) into table gp_emps
This will be my connection string for my FoxPro Table if I need it.
Dim FConnString As String = "Provider=vfpoledb;Data Source=Z:\update_dwprm01\gp_emps.DBF;Collating Sequence=general;"
Dim FPdbConnection As New OleDbConnection(FConnString)
Thanks in advance.

You appear to be on the right track. A few minor issues. The connection string should have the provider as
Provider=vfpoledb.1;
The Data Source component of the string should point to the physical directory where the .dbf files are located and NOT the specific .DBF file itself.
Data Source=Z:\YourShareOnServer\SomePath
The query itself looks ok as you have it coded. HOWEVER, when you DO get more into .net select, insert, update, delete, you will DEFINITELY need to look into using PARAMETERIZED queries to prevent SQL-Injection (even though not practical with VFP since it would just choke on comment / hack attempts), but is still good to be in the practice.
Build your Command and have "?" as a place-holder for the "parameters", then add parameters in the same order as your "?" placements in the query such as:
dim OleDbCommand oCmd = new OleDbCommand();
oCmd.CommandText = "SELECT DISTINCT * from DWEmployee " _
+ "where cono <> ? and officeno <> ? AND cono <> '' AND officeno <> ''"
' Only sampling with first 2 as parameters to get the idea...
oCmd.Parameters.Add( "parmCONO", "XX" );
oCmd.Parameters.Add( "parmOffice", "XX" );
SConn.Open()
da = New OleDbDataAdapter(oCmd, SConn)
da.SelectCommand.CommandTimeout = 90
continue with filling the data table...
I've had many posts out for VFP, OleDB and C#, but the principles all are the same. It's been a while since using OleDB connectivity but you are getting there.

Related

Pass parameter to a query from another query in Access

I have a parameterized query GET_CUSTOMER:
SELECT * FROM Customer WHERE id = [customer_id]
I want to call this query from another query and pass it a parameter:
SELECT * FROM GET_CUSTOMER(123)
Note the above code is not valid, it is here to give you an idea of what I'm trying to do. Is it possible to do this in MS Access?
UPDATE 1:
The queries I posted are for example. The actual queries are much more complex. I know I can use table joins, but in my specific case it would be much easier if I could run parameterized queries inside other queries (that are parameterized as well). I can't use access forms because I'm using access with my .NET application.
This is how I end up solving this with help of https://stackoverflow.com/a/24677391/303463 . It turned out that Access shares parameters among all queries so there is no need to specifically pass parameters from one query to another.
Query1:
SELECT * FROM Customer WHERE ID > [param1] AND ID < [param2]
Query2:
SELECT * FROM Query1
VB.NET code:
Dim ConnString As String = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=Database.mdb"
Dim SqlString As String = "Query2"
Using Conn As New OleDbConnection(ConnString)
Using Cmd As New OleDbCommand(SqlString, Conn)
Cmd.CommandType = CommandType.StoredProcedure
Cmd.Parameters.AddWithValue("param1", "1")
Cmd.Parameters.AddWithValue("param2", "3")
Conn.Open()
Using reader As OleDbDataReader = Cmd.ExecuteReader()
While reader.Read()
Console.WriteLine(reader("ID"))
End While
End Using
End Using
End Using
You can build the SQL on the fly.
MyID = prompt or get from user some ID
strSQl = "Select * from tblCustomer where ID in " & _
"(select * from tblTestCustomers where id = " & MyID
So you can nest, or use the source of one query to feed a list of ID to the second query.

Data type to be used to store 10 digit mobile number?

In my current vb.net (visual studio 2010) project I am dealing with SQL Server CE data base.
For storing mobile numbers, I am using nvarchar data type for Mobile_no field.
while testing i have entered 1234567890 in field Mobile_no successfully..
But at the time of retrieval i am getting this error :
Expression evaluation caused an overflow. [Name of function (if known)=]
So what should i do to store mobile numbers in sql ce data base ?
EDIT :
Code for Insert :
Dim SQLquery As String
Dim enumber As String
enumber = 1234567890
insqertSql = "INSERT INTO tbl_cust(c_id,Mobile_no) VALUES(#CId, #Phno)"
Dim cmd As New SqlCeCommand(insqertSql, con)
cmd.Parameters.Add("#CId", c_id)
cmd.Parameters.Add("#Phno", enumber)
cmd.ExecuteNonQuery()
Query for retrieval :
SQLquery = "SELECT * FROM tbl_cust WHERE ePhone =" & txt_number.text
The problem is in the string concatenation in the retrieve query.
SQLquery = "SELECT * FROM tbl_cust WHERE ePhone =" & txt_number.text
Here, you miss the single quotes that should enclose a string value when used as a WHERE condition.
However, in your INSERT query you use a parameterized approach, why you don't use the same approach for the select?
SQLquery = "SELECT * FROM tbl_cust WHERE ePhone = #number"
Dim cmd As New SqlCeCommand(SQLquery, con)
cmd.Parameters.Add("#number", txt_Number.Text)
SqlCeDataReader reader = cmd.ExecuteReader()
........
If you use a parameterized query, the proper handling of string quotes, decimal numbers and date formatting is passed to the underlying framework code that knows better than you and me how to pass these values to the database engine. Also, the parameterized query remove any possibilities of Sql Injection.

How do I query SQL data then insert or update depending on the result

I am a beginner at this. But let me explain what I need to do and show you my code
I have a CSV file.
inside the CSV I have a projectnumber, city,state,country
I have a SQL table with the same column
I want to use vb.net to check if projectnumber exists in sql table
if exists then I want to run update statement.
if it does not exists then I want to run insert statement.
I have the program working . but I am just wondering if this would be the correct way or my code is some hack way of doing it.
LEGEND:
DTTable is data table with CSV inside
DT is data table with SQL result data
First I fill insert all lines in the CSV into a data table
Dim parser As New FileIO.TextFieldParser(sRemoteAccessFolder & "text.csv")
parser.Delimiters = New String() {","}
parser.ReadLine()
Do Until parser.EndOfData = True
DTTable.Rows.Add(parser.ReadFields())
Loop
parser.Close()
then I use oledbdataadapter to run the select query and fill another data table with the result of the select statement
SQLString = "select * from tblProjects where ProjectID='" & DTTable.Rows.Item(i).Item("ProjectNumber") & "'"
da = New OleDb.OleDbDataAdapter(SQLString, Conn)
da.Fill(dt)
then I run if statement
If dt.Rows.Count = 0 then
SQLString = "INSERT STATEMENT HERE"
oCmd = New OleDb.OleDbCommand(SQLString, Conn)
oCmd.ExecuteNonQuery()
Else
SQLString = "UPDATE STATEMENT HERE"
oCmd = New OleDb.OleDbCommand(SQLString, Conn)
oCmd.ExecuteNonQuery()
End if
ALL above code is run inside a for loop, to go through all the lines in the CSV
For i = 0 To DTTable.Rows.Count - 1
what do you think?
please advise
thank you
Personally, I wouldn't use .NET. I would import the table into a temp SQL Server table and then write my queries to insert/update data from the temp table to the regular table. This is certainly the way you want to go if the dataset is large.
If this is a process you need to repeat frequently, you could make an SSIS package.
I'd run the select query using datareader = command.ExecuteReader(). Then:
If datareader.Read() then
'Update query using datareader(0) as a where predicate goes here
ElseIf datareader(0) = Nothing then
'Insert query goes here
End If
I should say, I'm a relative novice too though, so maybe others can suggest a more elegant way of doing it.

Select all data from 1 column

I have code that is supposed to take all "course names" from a module based on what school is chosen.
For example the school of biology has the modules "biochemistry" and "marine biology". I need to select both of these in order to use in a calculation.
Currently when the code is run it will only take the first module ie "biochemistry" but I need it to select all of the modules.
Can anyone help?
Dim courseSelectCom As New SqlCommand("SELECT course_name FROM course where school= '%"schoolSelect & "' ", _
connection)
The first thing to do on your query is to use a parametrized query.
This will avoid Sql Injection and parsing problems.
Then you shoud explain why you use the wildcard % in front of SchoolSelect.
Do you have many kind of schools that ends with the same suffix and do you want to retrieve all of them?
Last, you should use a DataReader to loop over the returned data or a DataAdapter to fill a DataTable.
So summarizing
Dim sb = new StringBuilder()
Using connection = New SqlConnection("your_con_string_here")
connection.Open()
Dim courseSelectCom = New SqlCommand("SELECT course_name FROM course where school=#schoolName", connection)
courseSelectCom.Parameters.AddWithValue("#schoolName", SchoolSelect.Text)
Dim reader = courseSelectCom.ExecuteReader()
while reader.Read()
sb.AppendLine(reader("course_name")) ' or add to some kind of list to reuse'
End While
End Using
Console.WriteLine(sb.ToString())
if you want to store the data in a DataTable then replace the DataReader loop with
Dim dt = New DataTable()
Dim da = New SqlDataAdapter(courseSelectCom)
da.Fill(dt)
And you have a DataTable object to use for binding to a DataGridView, Listbox or whatever....
What are you using for Executing the command?
If you use ExecuteScalar you will get only first result.
Use ExecuteReader and read through or Use DataAdapter and fill a DataSet with it.
Dim courseSelectCom As New SqlCommand("SELECT course_name FROM course where school=#School", _connection)
courseSelectCom.Parameter.Add("#School", SqlDbType.VarChar).Value = SchoolSelect.Text
SchoolSelect is the textbox from which you select school
If you want all the courses in a comma delimited list, then use group_concat (assuming you are using MySQL):
SELECT group_concat(course_name)
FROM course
where school= '%"schoolSelect & "'
This returns one row, with all the courses in a single column, like 'biochemistry,marine biology'.
To do this in SQL Server, you can do:
select stuff((select ','+course_name from course where school= '%"schoolSelect & "' for xml path ('')),
1, 1, '') as coursenames
SQL Server does not have a native aggregate string concatenation operator, so this uses XML features of the database.
I think it would be written as:
Dim courseSelectCom = New SqlCommand("select stuff((select ','+course_name from course where school= '%"schoolSelect & "' for xml path ('')), 1, 1, '') as coursenames", connection)
You need something like this:
Dim reader = courseSelectCom.ExecuteReader()
reader.Read()
reader("course_names")

Update table while reading

I'm writing a piece of code (VB.NET) to cleanse a (quite big) table of data.
I am connecting to my SQL database, looping through the table, cleansing the data and adding the cleansed data in a different column.
As i'm currently doing an update to my database for each record in the same loop as where i am cleansing the data, i am wondering if there is a more efficient way of doing this, where i would cleanse the data and afterwards send all the updated records to the database in one go.
Simplified code:
'Connect
SQLConn.ConnectionString = strConnection
SQLConn.Open()
SQLCmd.Connection = SQLConn
SQLConn2.ConnectionString = strConnection
SQLConn2.Open()
SQLCmd2.Connection = SQLConn2
'Set query
strSQL = "SELECT Column1 FROM Table1"
SQLCmd.CommandText = strSQL
'Load Query
SQLdr = SQLCmd.ExecuteReader
'Start Cleansing
While SQLdr.Read
Cleansing()
'Add to database
strSQL2 = "UPDATE Table1 SET Clean_data = '" & strClean & "' WHERE Dirty_Data = '" & SQLdr(0).ToString & "'"
SQLCmd2.CommandText = strSQL2
SQLCmd2.ExecuteNonQuery()
End While
'Close Connections
SQLdr.Close()
SQLConn.Close()
SQLConn2.Close()
I'm guessing (from searching for a solution) that it is possible to do the update outside of my loop, but i can't seem to find how to do it specifically.
Many thanks!
Your code is taking a long time because the update is doing a full table scan for every record. You can speed it up by adding an index on the column "Dirty Data".
Essentially, you are reading the data in the select statement. Cleaning one row, and then updating it. The preferred "set-based" approach is more like:
Ideally, you would like to do:
update table1
set column1 = <fix the dirty data>
where column1 <is dirty>
And you have some options in SQL, in terms of replace() and case and like (for instance) that can help with this process.
But you already have the cleaning code external to the database. For this, you want to create and open a cursor, process the record, and then write back. Cursors are relatively slow, compared to in-database operations. But, this is exactly the situation they were designed for -- external code to be applied to individual records.