VB.Net -- Bulk Insert XML into Existing SQL Server Table - sql-server

I recently figured out how to export data as XML from SQL Server using VB.Net. I use three SQL statements and dimension an XPath document to add the root tags to the export:
Dim connectionString As String
Dim connection As New SqlConnection
Dim command As New SqlCommand()
Dim sql = "select * from scheduledata for xml auto, elements " & _
"select * from costdata for xml auto, elements " & _
"select * from csintegrationdata for xml auto, elements "
connectionString = "Data Source=(localdb)\v11.0; _
Initial Catalog=localACETest;Integrated Security=True"
connection = New SqlConnection(connectionString)
connection.Open()
command.CommandText = sql
command.Connection = connection
command.CommandType = CommandType.Text
Dim xmlRead As XmlReader = command.ExecuteXmlReader()
Dim xp As New XPath.XPathDocument(xmlRead)
Dim xn As XPath.XPathNavigator = xp.CreateNavigator()
Dim xd As New XmlDocument
Dim root As XmlNode = xd.CreateElement("Data")
root.InnerXml = xn.OuterXml
xd.AppendChild(root)
Dim fStream As New FileStream(Directory, FileMode.Create, FileAccess.ReadWrite)
xd.Save(fStream)
fStream.Close()
I would like to be able to re-import this data into the SQL tables using VB, but I'm having some trouble. The code I'm using is this:
Using sqlconn As New SqlConnection(connectionString)
Dim ds As New DataSet()
Dim sourcedata As New DataTable()
Dim ii As Integer = 0
ds.ReadXml("C:\Users\coopere.COOPERE-PC\Desktop\Test.xml")
sqlconn.Open()
Using bulkcopy As New SqlBulkCopy(sqlconn)
sourcedata = ds.Tables(0)
bulkcopy.DestinationTableName = "CSIntegrationData"
bulkcopy.ColumnMappings.Add("Period", "Period")
bulkcopy.ColumnMappings.Add("Program", "Program")
bulkcopy.ColumnMappings.Add("CostControlAccount", "CostControlAccount")
...
bulkcopy.WriteToServer(sourcedata)
End Using
sqlconn.Close()
End Using
When doing this, I get an error: System.InvalidOperationException: The given ColumnName 'CostControlAccount' does not match up with any column in data source.
I believe the reason for this is because one of the tables that exported to XML has a column full of NULL values which aren't winding up anywhere in the XML. But that won't always be the case -- oftentimes, there will be values.
Considering SqlBulkCopy's columnmappings can't handle accepting null values, how can I handle null values in my Export/Import? I'm also open to a different route entirely.

After much digging, I found this link.
As part of the FOR XML function you can tack on XSINIL at the end to handle null values. The resulting XML is below.
select * from TABLENAME for xml auto, elements XSINIL
<ScheduleWorkPackage xsi:nil="true" />

Related

SqlDataAdapter not filling data table with SQL Where Clause

Attempting to fill a data table using SqlDataAdapter with a WHERE clause but it returns nothing. The SQL command itself returns data from SSMS and removing just the WHERE clause in code fills data table as expected.
Dim adapter As New SqlDataAdapter
Dim datatable As New DataTable
Using cnn As New SqlConnection(connectionString)
cnn.Open()
adapter = New SqlDataAdapter("SELECT * FROM [MyProjectDtbl] WHERE zipcode = 22021", cnn)
adapter.Fill(datatable)
adapter.Dispose()
End Using
Digging through the Select command EventSink, I found:
Unable to cast object of type 'System.Data.SqlClient.SqlInternalConnectionTds' to type 'System.Data.SqlClient.SqlInternalConnectionSmi'
Try it with parameters.
Private Sub OPCode()
Dim dt As New DataTable
Using cnn As New SqlConnection(connectionString),
cmd As New SqlCommand("SELECT * FROM [MyProjectDtbl] WHERE zipcode = #zip", cnn)
cmd.Parameters.Add("#zip", SqlDbType.Int).Value = 22021
cnn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Debug.Print(dt.Rows.Count.ToString)
End Sub

SQL Server database population pre-existing Data Table and fields (FORM). NO database file

Here is my general understanding of database from what I read so far: Save / Update / Delete to pre-existing file made that binds to form thru SQL.
Here is what I am trying to do - I have a pre-made Data Table in Form with all columns defined. Once app is closed or certain functions ran, I need that data to be saved / updated in SQL (on local). Once app is open I need all that data to be preserved.
So far I have NOT found a single solution to it anywhere most refer to binding to an existing file. When I worked with Excel data transfer cells had to be defined and referenced in form for population.
My assumption is when a database from VB.NET is used, table with values can be created automatically saved/loaded/updated. However this is only my assumption since I never worked with SQL before. I am not sure if I need to manage an actual database file I created with all the values and then bind them to data table. For example DataTable cell XX to database column XX.
Here is what I done so far I have created database and added to my project. I tried few codes and I keep getting Dataset Empty even though there is Data in Table I tried to use DataTable as well but so far nothing has worked.
Please suggest on what I am doing wrong also additional information regards to databases will be great. As per previous I do know how binding works when actual file exist. But creating and managing is confusing to me since I keep thinking there should be a binding file.
Dim connetionString As String
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
connetionString = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
sql = "SELECT BN FROM DataTable" ' BN is my column name and DataTable is the name of my Table where data gets populated. This is also confusing to me How does it know which value is what? Is there are space/word/characters requirements?
' adapter.TableMappings.Add("DataTable", sql)
If ds.Tables.Count > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds)
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf ds.Tables.Count = 0 Then
MsgBox("Empty data")
End If
End Sub
Code I use to Create /Save Database. As per previous all columns/formats are pre-made, loaded.
Dim connetionString As String
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
connetionString = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
sql = "Select BN FROM DataTable"
adapter.TableMappings.Add("BN", sql)
If DataTable.RowCount > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds, "BN")
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf DataTable.RowCount = 0 Then
MsgBox("Empty data")
End If
End Sub
Please see more info below:
Data Table columns/format are structured for visual representation.
When User start the App Database can be empty/Can contain Values.
When users Runs certain function Closes App values are save and only values.
If I would you an MS Access I would structure same table/values and cross reference it with form values. Form Values come from outside source and Format/Qty is always known.
Hope this helps to have a cleaner look at my issue. Perhaps SQL is not a right choice for me? Does SQL needs to be build before value manipulation.
UPDATE: I Got rid of the Invalid Object error. Table had to be created 1st as I originally thought. However, My DataSet always comes up as EMPTY when I try to save... Cells do contain BN data as" 1,2, ....) Even if I to remove "If" logic Save and Load table comes out as empty. Something does load because when I try to ADD BN it tells me binding bla bla bla(different issue)
CODE:
Private Sub SaveData()
Dim connetionString As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Dim sql As String = "SELECT BN FROM DataTable_d"
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet()
adapter.TableMappings.Add("BN", sql)
If ds.Tables.Count > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds, "BN")
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf ds.Tables.Count = 0 Then
MsgBox("Empty data")
End If
End Sub
UPDATE: I got all the things working but I can't save multiple rows..... Could really use some help
In your SQL query remove WHERE DataTable ='. This statement is looking for a column name DataTable which I assume does not exist. The WHERE clause is used to help filter your query. You only use WHERE on column names in your table.
For instance:
SELECT BN FROM DataTable
will return all values from the BN column from DataTable.
Note that if you have multiple columns, the above query will still only return values from BN.
SELECT * FROM DataTable
will return every value in DataTable.
A helpful site to look at documentation for SQL is w3schools.
Let's start with just displaying some data. Add a DataGridView to a Form. You can call LoadData() from a button. I am not very sure of you connection string but give it a try.
Private dt As DataTable
Private sql As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Private Sub LoadData()
'***EDIT*** Add instantiation line
dt = New DataTable()
'The Using...End Using blocks will close and dispose your database objects
'even if there is an error
Using cn As New SqlConnection(sql)
'You can pass the command text and the connection directly to the constructor
'In the select statement use the actual names of the field and table as they appear in the database.
Using cmd As New SqlCommand("Select BN From [Insert the name of the table in the database]", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dt
End Sub
This is the simplest way I can think of to display data. We will proceed with changing the data once this works. If you get an error on cn.Open() We will have to work on the connection string.
****EDIT****
Private Sub TestConnection()
Dim sql As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Using cn As New SqlConnection(sql)
cn.Open()
End Using
End Sub

How can you fill combobox in vb.net with column name from Microsoft SQL Server

How to fill combobox in vb.net with column name from Microsoft Sql Server? I have table name called Table_Categories. I wish to fill the combobox with the column names of that table . I am also planning on adding column names in the table using vb.net as its front end . how can I do it ?
Public Sub Categories()
Dim Connect As New SqlConnection
Dim Adapter As New SqlDataAdapter
Dim DataTable As New System.Data.DataTable
Dim Query As String
ConnectionString = "Data Source=LUSPOC-PC;Initial Catalog=Sales_Invnetory;Integrated Security=True"
Connect = New SqlConnection(ConnectionString)
Connect.Open()
Connect.ChangeDatabase("Sales_Inventory")
Query = "select Column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Table_Categories'"
Adapter.SelectCommand = New SqlCommand(Query, Connect)
Adapter.Fill(DataTable)
Admin.items_category_combobx.DataSource = DataTable
Admin.items_category_combobx.DisplayMember = "Column_name"
Admin.items_category_combobx.ValueMember = "Column_name"
End Sub
Connect.ChangeDatabase("database-name")
Query = "select Column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='your-Table-name'"
Admin.items_category_combobx.DataSource = DataTable
Admin.items_category_combobx.DisplayMember = "Column_name"
Admin.items_category_combobx.ValueMember = "Column_name"
Change your query as above and you will get column names in your dataset. For adding column, take column name and type from user. build and execute an alter table query for adding column from it.
Using sqlconn As New SqlConnection("your connection string")
sqlconn.Open()
Using SqlCommand As New SqlCommand("select Column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Table_Categories'", sqlconn)
SqlCommand.CommandTimeout = 0
Using sqlAdp As New SqlDataAdapter(SqlCommand)
sqlAdp.Fill(dt)
End Using
End Using
End Using
ComboBox1.DataSource = dt
ComboBox1.DataTextField = "Column_name"
ComboBox1.DataValueField = "Column_name"
ComboBox1.DataBind()

Inserting contents of CSV file into database loses 1 record

I have an application that imports a CSV file (no header row) and writes the contents into a datatable. The datatable is then passed on as a parameter to a function in my DAL that uses the sqlBulkCopy command to write the data to a SQL Server database.
I have run tested the code as both a Webforms and Windows Forms environment and noticed that in both cases the first row of data is lost. Does anyone know why this should be the case and how I can rectify it? Thanks for any help.
I should add that this doesn't happen if the CSV file has a header row.
UI
Dim csvFileFolder As String = "D:\PROJECTS\Letters(DOTNET)\TextFiles\"
Dim csvFileName As String = "quad1a.txt"
Dim connString As String = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" _
& csvFileFolder & ";Extended Properties=""Text;HDR=No;FMT=Delimited"""
Dim conn As New Odbc.OdbcConnection(connString)
'Open a data adapter, specifying the file name to load
Dim da As New Odbc.OdbcDataAdapter("SELECT * FROM [" & csvFileName & "]", conn)
'Then fill a data table, which can be bound to a grid
Dim dt As New DataTable
da.Fill(dt)
grdQuad.DataSource = dt
grdQuad.DataBind()
LettersBLL.TemporaryPatientManager.InsertIntoBulkTable(dt)
DAL
Public Shared Function InsertIntoBulkTable(dt As DataTable) As DataTable
Using myConnection As New SqlConnection(ApplicationConfiguration.ConnectionString)
Using sqlBulkCopy As New SqlBulkCopy(myConnection)
'Set the database table name
sqlBulkCopy.DestinationTableName = "tblBulkInsert"
myConnection.Open()
sqlBulkCopy.WriteToServer(dt)
myConnection.Close()
End Using
End Using
Return Nothing
End Function
Try this...
Dim connString As String = "Driver={Microsoft Text Driver (*.txt; *.csv)};HDR=No;Dbq=" _& csvFileFolder & ";Extended Properties=""Text;HDR=No;FMT=Delimited"""
Added 'HDR=No' to your connection string
Or try specifying your sqlbulkcopy column mappings.
msdn.....
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.columnmappings.aspx
Example.....
http://www.codeproject.com/Articles/18418/Transferring-Data-Using-SqlBulkCopy

write result of for xml raw query to file vb.net

I have a for xml raw select query that returns a xml string in server2005 and i would like to write that string to a file using vb.net.
I found that if you fill a dataset with the result of the sql the first cell is the restult.
How slow was i?!
----------Code Below-------
Dim connection As SqlConnection
Dim adapter As SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
Dim stringxml As String
Dim SqlCon1 As String = "Data Source=SQLSERVER;Initial Catalog=DATABASE;Integrated Security=SSPI;"
connection = New SqlConnection(SqlCon1)
sql = "select * from tblProduct for xml auto"
Try
connection.Open()
adapter = New SqlDataAdapter(sql, SqlCon1)
adapter.Fill(ds)
connection.Close()
stringxml = ds.Tables(0).Rows(0).Item(0)
Using writer As StreamWriter = New StreamWriter("c:\testings\picktoday.xml")
writer.Write(stringxml)
End Using
MsgBox("Done")
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Using strmWrite as System.IO.StreamWriter(filePath)
strmWrite.WriteLine(xmlString)
End Using
Obviously, just fill in the filePath variable with the directory and name of your file. The xmlString variable will be your XML.
I just want to add to the accepted answer when we have a long output we can get data in multiple rows so we can use the following code
dim xmloutput as string
For Each item As DataRow In ds.Tables(0).Rows
xmloutput += item.Item(0)
Next

Resources