Using SqlBulkCopy with 2 Different Connection Strings - sql-server

I have an application that gets information from one server (server config stuff) and puts it into a centralized database on another server. There are several servers that I loop over from a text file. I'm writing this application to eliminate the need for linked servers.
I'm trying to use SqlBulkCopy for copying the data but I'm running into problems. I have been successful using SqlBulkCopy with a single SQL connection but when I try to use 2 different SQL connections I run into problems. The data never reaches its destination database. I have debugged through the code and can see that it reaches the try/catch but it appears that the command bulkcopy.WriteToServer(reader) it doesn't actually write any data to SQL.
Dim connectionString As String = "Server= <ThatServer>; integrated security=true"
Dim connectionString2 As String = "Server= <MyServer>; Initial Catalog = <CentralizedDatabase>; integrated security=true"
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
sourceConnection.Open()
Dim commandSourceData As SqlCommand = New SqlCommand("<mySQLcommand>", sourceConnection)
Dim reader As SqlDataReader = commandSourceData.ExecuteReader
Using sourceConnection2 As SqlConnection = _
New SqlConnection(connectionString2)
sourceConnection2.Open()
Using destinationConnection As SqlConnection = _
New SqlConnection(connectionString2)
Using bulkcopy As SqlBulkCopy = _
New SqlBulkCopy(destinationConnection)
bulkcopy.DestinationTableName = _
"<MyTableName>"
Try
bulkcopy.WriteToServer(reader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
reader.Close()
End Try
End Using
End Using
sourceConnection2.Close()
End Using
sourceConnection.Close()
End Using
Can anyone see what I'm doing wrong? Thanks in advance!
**Solved. Here's my code that works:
Dim connectionString As String = "Server = <ThatServer>; Initial Catalog = <sourceDB>; integrated security = true"
Dim connectionString2 As String = "Server= <MyServer>; Initial Catalog = <destinationDB>; integrated security=true"
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
Dim commandSourceData As SqlCommand = New SqlCommand(<TSQL>, sourceConnection)
sourceConnection.Open()
Dim reader As SqlDataReader = commandSourceData.ExecuteReader()
Using destinationConnection As SqlConnection = _
New SqlConnection(connectionString2)
destinationConnection.Open()
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(destinationConnection)
bulkCopy.ColumnMappings.Add("SourceColumn1", "DestinationColumn1")
bulkCopy.ColumnMappings.Add("SourceColumn2", "DestinationColumn2")
bulkCopy.ColumnMappings.Add("SourceColumn3", "DestinationColumn3")
bulkCopy.ColumnMappings.Add("SourceColumn4", "DestinationColumn4")
bulkCopy.ColumnMappings.Add("SourceColumn5", "DestinationColumn5")
bulkCopy.ColumnMappings.Add("SourceColumn6", "DestinationColumn6")
bulkCopy.ColumnMappings.Add("SourceColumn7", "DestinationColumn7")
bulkCopy.DestinationTableName = "<destinationTable>"
bulkCopy.WriteToServer(reader)
End Using
destinationConnection.Close()
End Using
reader.Close()
sourceConnection.Close()
End Using

Related

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

Long running SP never ends using sqlCommand

I've got a quite expensive stored procedure in my SQL Server database. Launching it from the SQL Server Managment Studio requires some minutes. But I can't launch it via code using SqlCommand.
I've got this code:
spExecQuery = "EXEC [schema].[storedName]"
If I use this vb.NET snippet:
Using sqlCmd As SqlCommand = New SqlCommand(spExecQuery, conn)
sqlCmd.ExecuteNonQuery()
End Using
The script ends with "Timeout expired" error. But if I do:
Using sqlCmd As SqlCommand = New SqlCommand(spExecQuery, conn)
sqlCmd.CommandTimeout = 0
sqlCmd.ExecuteNonQuery()
End Using
The script never ends (it's running from at least 2 hours)... What am I missing? Thank you.
You need to specify first that it's a stored-procedure:
Using sqlCmd As SqlCommand = New SqlCommand(spExecQuery, conn)
sqlCmd.CommandType = CommandType.StoredProcedure
sqlCmd.CommandTimeout = 0
sqlCmd.ExecuteNonQuery()
End Using
You could also use QueueUserWorkItem to let the method run asynchronously, then you don't need to wait until it has finished:
Public Shared Sub ExecuteStoredProcedureAsync()
Threading.ThreadPool.QueueUserWorkItem(
New Threading.WaitCallback(AddressOf ExecuteStoredProcedure)
)
End Sub
Private Shared Sub ExecuteStoredProcedure(threadState As Object)
Dim sw = New Stopwatch()
sw.Start()
Try
' add code or call of long running method here '
Log.WriteInfo(String.Format("ExecuteStoredProcedure(async call) executed successfully, execution-time: {0}.", sw.Elapsed))
Catch ex As Exception
Log.WriteError(String.Format("Exception in ExecuteStoredProcedure (async call), execution-time: {0}.", sw.Elapsed))
End Try
End Sub
It should work if you specify the CmdType.
If still not working, try using the SqlDataReader
cmd.Connection = conn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "proc_name"
Dim dr As SqlDataReader = cmd.ExecuteReader
try to add the command type to your sqlcommand
sqlCmd.CommandType = CommandType.StoredProcedure

Close database connection on SQL Server using ADO .NET

I'm connecting to database using ADO .NET:
Dim conn As SqlConnection
Dim sqlcmd As SqlCommand
Dim da As SqlClient.SqlDataAdapter
Dim table As DataTable
conn = New SqlConnection(Utilities.ConnectionString)
sqlcmd = New SqlClient.SqlCommand()
sqlcmd.Connection = conn
sqlcmd.CommandType = CommandType.StoredProcedure
sqlcmd.CommandText = "mySP"
sqlcmd.Parameters.Add(New SqlClient.SqlParameter("#param", param1))
da = New SqlClient.SqlDataAdapter()
da.SelectCommand = sqlcmd
table = New DataTable()
da.Fill(table)
conn.Close()
sqlcmd.Connection.Close()
That works good.
When I launch on SQL Server the command:
EXEC SP_WHO2
For each call made from the previous code in ADO .NET, I have in the field Command the value: "AWAITING COMMAND", and in the field Status the value is "sleeping".
What does this means? The connection to database is still active? What should I do in order to close db connection?
The fact that after few hours you receive errors about connections exausted means that somewhere in your code you don't dispose correctly of your connection.
The code above seems correct, but what happen if you have exceptions? Are you sure to handle correctly the situation when your code exits unexpectedly from a method, due to exceptions?
The correct approach to this situation is refactoring your code.
Introduce everywhere the Using pattern. So your code above become:
Dim conn As SqlConnection
Dim sqlcmd As SqlCommand
Dim da As SqlClient.SqlDataAdapter
Dim table As DataTable
Using conn = New SqlConnection(Utilities.ConnectionString)
Using sqlcmd = New SqlClient.SqlCommand()
sqlcmd.Connection = conn
sqlcmd.CommandType = CommandType.StoredProcedure
sqlcmd.CommandText = "mySP"
sqlcmd.Parameters.Add(New SqlClient.SqlParameter("#param", param1))
da = New SqlClient.SqlDataAdapter()
da.SelectCommand = sqlcmd
table = New DataTable()
da.Fill(table)
End Using
End Using
This approach will ensure that your disposable objects (connection and command) will be released correctly and you will remove the subtle problem of connection leakings.

How to programmatically attach with server instance through vb.net

I need to attach my database, that resided in the MyData directory of my application folder, to the instance of SQL server on client's machine. How to do it?
Could any body give me vb.net code for that so my application does it when run for the first time?
Someone suggested me
Dim cmd As New SqlCommand()
' Dim vrMyConString As String=
Dim conn As System.Data.SqlClient.SqlConnection ' = New SqlConnection(vrMyConString)
cmd.CommandText = "sp_attach_db 'e:\dbTest.mdf', 'e:\dbTest.ldf'"
'conn.connectionstring =
conn.open()
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = conn
cmd.executenonquery()
but on conn.open, it returns error, Object reference not set to an instance of object
Thanks
This works on my Vb.net application.
Make sure sure your connection string: vrMyConString is correct and pointing to your database and with the correct details and it should work
Dim conn As SqlConnection = Nothing
conn = New SqlConnection(vrMyConString )
conn.Open()
You may use ADO.NET provider Linq to SQL or Entity Framework API.

Directory pointing to self /creating application with a built-in database

I made a simple program with a database connection:
Dim con As New OleDb.OleDbConnection
Dim dbProvider As String
Dim dbSource As String
Dim ds As New DataSet 'holds table data
Dim da As OleDb.OleDbDataAdapter 'connection to database connectionobject
Dim sql As String
dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = C:/JIMMY.mdb"
con.Open()
sql = "select * from TURNING"
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "RECORDS")
con.Close()
Now I heard from someone that in order to make an application with a built in database, I should place the file inside the project.
C:\Users\User\documents\visual studio 2010\Projects\myProject\JIMMY.MDB
How do I make the directory dynamic? So, wherever I place the published application, will it work?
You can make it relative to the application, as explained in HOW TO: Determine the Executing Application's Path:
Dim path As String
path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
dbSource = "Data Source = " + Path.Combine(path, "jimmy.mdb")

Resources