PostgreSQL: command is already in progress - c#

My asynchronous function tries to select a single record from a table. This function accepts a few arguments passed from another function.
So, some processes (6 at least) can use it simultaneously. Often I get an error with the message "command is already in progress".
I know that the problem hides in the reader, because the reader is busy when another process tries to access it.
Let me publish the full code below:
async private void InsertToLog(List<Printer> APrinter, List<PrinterToGridBinds> AGridBind, int index)
{
if (!String.IsNullOrEmpty(APrinter[index].Type.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extBatchNumber.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extBatchCounter.Trim()) && !String.IsNullOrEmpty(AGridBind[index].extDIOCounter.Trim()))
{
string dio_count = "0";
string GetDIOCounter = string.Format(#"SELECT dio_counter FROM {0} WHERE device_type = '{1}' AND batch_number = '{2}' ORDER BY id DESC
LIMIT 1;", log_table_name, lst_PrinterStruct[index].Type, AGridBind[index].extBatchNumber);
try
{
NpgsqlCommand db_getCounter = new NpgsqlCommand(GetDIOCounter, conn);
if (conn.State != ConnectionState.Open)
conn.Open();
using (DbDataReader reader = await db_getCounter.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
dio_count = reader[0].ToString().Trim();
}
AGridBind[index].extDIOCounter = (Int32.Parse(dio_count) + Int32.Parse(AGridBind[index].extDIOCounter.Trim())).ToString();
string Insert_SQL = String.Format(#"INSERT INTO {0} (device_type, batch_number, start_date, batch_counter, dio_counter) VALUES ('{1}', '{2}', '{3}', '{4}', '{5}') ON CONFLICT ON CONSTRAINT unique_log_key DO UPDATE SET batch_counter='{4}', dio_counter='{5}';", log_table_name, APrinter[index].Type.Trim(),
AGridBind[index].extBatchNumber.Trim(), DateTime.Now.ToString(), AGridBind[index].extBatchCounter.Trim(), AGridBind[index].extDIOCounter.Trim());
var db_cmd = new NpgsqlCommand(Insert_SQL, conn);
int res = await db_cmd.ExecuteNonQueryAsync();
}
catch (Exception e)
{
string FMessage = String.Format("Printer {0} \r\n Can not write to table\r\n Error: {1}",
lst_PrinterStruct[index].Name, e.Message);
MessageBox.Show(FMessage);
}
finally
{
conn.Close();
}
}
}
As you can see, the reader is wrapped by using here.
Anyway, I have what I have (an error). So, my question is how to avoid this error message (I'm about "command is already in progress")?
I have a few ideas about possible decisions. Maybe:
Set the DbDataReader as parameter. And the name of the reader can be generated by the Random function. But I don't know how to do that.
Wait until the current process has finished and closes the reader, then run the second etc. But I don't know how to tell the new process to wait until the previous has finished.
So, I need your help, guys.

If several threads share one database connection, you have to synchronize them so that only one of them uses the connection at the same time. You can only run one statement at a time in a PostgreSQL database session.
Since synchronization is cumbersome and may hurt your concurrency, you'd be better off using a connection pool, and each thread requests a connection from the pool if it needs one.

I have encountered same problem in VB.Net when migrating OleDB program to PNGSQL.
My program executed simply a loop to read some records returned by a simple SQL SELECT.
'*******************************************************************
'* SelectMouvements()
'*******************************************************************
Private Function SelectMouvements() As Integer
SQL = _
<sql-select>
SELECT *
FROM mouvements
INNER JOIN comptes
ON comptes.no_compte = mouvements.personnal_account
LEFT OUTER JOIN cartes
ON cartes.no_carte = mouvements.no_carte
</sql-select>
Dim cmd As New NpgsqlCommand(SQL, cn)
Dim dr As NpgsqlDataReader
dr = cmd.ExecuteReader()
While dr.Read()
grid.Rows.Add()
With grid.Rows(iRow)
.Cells(0).Value = dr("communication")
...
End With
call NormalizeSomeFields(dr("name"))
End While
End Sub
The problem with my code that doesn't exist when using OleDb is that NormalizeSomeFields() function was opening a second DataReader.
Private Sub NormalizeSomeFields(ByRef sNom as String)
SQL =
<sql-select>
SELECT NewNom
FROM aliasnom
WHERE Nom = <%= AddQuote(sNom) %>
<sql-select>
Dim cmdNom As New NpgSqlCOmmand(SQL, cn)
Dim drNom As NpgsqlDataReader
drNom = cmdNom.ExecuteReader()
If drNom.Read() Then
sNom = drNom(0)
End If
drNom.Close()
End Sub
This program is returning NpgsqlOperationInProgresException on cmdNom.ExecuteReader() line.
SOLUTION
To solve this problem I have defined another NpgsqlConnection named cn2 just after code that is defining cn connection as in following lines
cn = New NpgsqlConnection(cs)
Try
cn.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
cn2 = New NpgsqlConnection(cs)
Try
cn2.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
and I use it now when second DataReader is defined
Dim cmdNom As New NpgSqlCOmmand(SQL, cn2)
NPGSQL seems to refuse multiple sets ... but accepts multiple connections !

Related

Close SqlDataReader if there are no more rows left to read - C#

This is causing me a headache. I know this question (or atleast variants of it) has been asked many times but before one flags it as a duplicate please consider the following code:
string myConnectionString = myConnectionString = ConfigurationManager.ConnectionStrings["DBCS"].ToString();
SqlConnection mySQLConnection;
SqlCommand mySQLCommand;
SqlDataReader mySQLDataReader;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection);
mySQLCommand.Connection = mySQLConnection;
mySQLCommand.Connection.Open();
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
if (mySQLDataReader.HasRows)
{
if (mySQLConnection.State == ConnectionState.Open)
{
while (mySQLDataReader.Read())
{
//Perform Logic : If the last record being returned meets some condition then call the below method
MethodCalled();
}
}
}
}
MessageBox.Show("Connection state: " + mySQLConnection.State);
}
I would like to find a way to either:
Close the reader after it has finished reading
Break out of the while-loop when it has finished reading and there are no more rows left
But I just keep on getting a SqlException stating the following:
invalid attempt to call read when reader is closed
Just from broad observation, I can trace that error is due to me returning data that contains one row only. The problem is that after it has read that row, the compiler goes back to While(mySQLDataReader.Read()){} and attempts to read through a table that does not contain any rows.
I attempted the following:
Wrapping the ExecuteReader() from the command object in a using block so that it automatically closes the reader and the connection respectively once it has done reading like so:
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
//Logic performed
}
Just before the closing brace of the while-loop, I tried checking if there are any more rows left/returned from the sql command and breaking out the loop once that condition is satisfied:
if(mySQLDataReader.HasRows == false) //No more rows left to read
{
break; //break out of loop
}
Both attempts were unsuccessful. How can I get around this?
It must be one of the following 3 things:
You're using Read() OUTSIDE the using block. Remember that using block will implicitly call Close and Dispose on your reader. Thus any Read() calls must be placed inside the using block.
The body of your using block is explicitly closing the reader. This seems improbable.
Apparently you have declared your mySQLDataReader at a higher level. It could be that some other (async) code is closing the reader. This also is unlikely. You shouldn't, in most cases, define a DataReader at global level.
Edit
Reading the full code block that you have posted now, I'd suggest a few changes. Can you run the following and tell us if it runs:
using (var mySQLConnection = new SqlConnection(myConnectionString))
{
mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection, mySQLConnection);
mySQLCommand.Connection.Open();
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
while (mySQLDataReader.Read())
{
//Perform Logic : If the last record being returned meets some condition then call the below method
MethodCalled();
}
}
}
If this version runs fine, we can then dig the problem better.
If there is no data to iterate, while loop will not execute at all. Do you need to check for HasRows as such? Also, you should use CommandBehavior.CloseConnection when you are creating data reader. This will make sure that underlying connection is closed once you have read through it.
Should if call SqlDataReader.HasRows if I am calling SqlReader.Read
SQLDataReader Source Code
using (SqlConnection mySQLConnection = new SqlConnection(myConnectionString))
{
using (SqlCommand mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection))
{
mySQLConnection.Open();
SqlDataReader mySQLDataReader = mySQLCommand.ExecuteReader(CommandBehavior.CloseConnection);
while (mySQLDataReader.Read())
{
//Code logic here
}
// this call to mySQLDataReader.Close(); will close the underlying connection
mySQLDataReader.Close();
}
MessageBox.Show("Connection state: " + mySQLConnection.State);
}

C# reader is closed while reading?

I am running a C# windows application, and I get an error message when trying to use a datareader. The error message is:
"Invalid attempt to call CheckDataIsReady when reader is closed."
I used stop point and saw that the code works fine until it enters the "while" loop. Once inside, it gives the error message.
I have tried to do it without closing the previous reader, but then the message changed to something like "there is already an open reader" or some such.
Here's the code:
conn = new SqlConnection(DBConnectionString);
SqlCommand select_cmd = new SqlCommand("SELECT usrRealname, usrIsowner FROM tblUSERS WHERE usrNum = " + UserID, conn);
SqlCommand select_orders = new SqlCommand("SELECT orderNum, orderBy, orderShipadrs, orderDate, orderTotal FROM tblOrders WHERE orderDeliveryDate is NULL AND fkorderTakenbyusrnum = " + UserID, conn);
conn.Open();
SqlDataReader dr = select_cmd.ExecuteReader();
dr.Read();
CurrentUser User = new CurrentUser(Convert.ToString(dr[0]), UserID, Convert.ToBoolean(dr[1]));
DetailsLabel.Text = String.Format("Welcome {0}, ID number {1}. {2}", User.getname, UserID, User.getOwner);
dr.Close();
SqlDataReader orders = select_orders.ExecuteReader();
while (orders.Read())
{
UnfulfilledOrders CurrentOrder = new UnfulfilledOrders(Convert.ToInt32(dr[0]), Convert.ToString(dr[1]), Convert.ToString(dr[2]), Convert.ToString(dr[3]), Convert.ToInt32(dr[4]));
OrderList.Items.Add(CurrentOrder);
}
What I'd trying to do is add class (UnfulfilledOrders) type objects to a listbox (OrderList).
The thing that baffles me is that I used such a while loop in a previous form in the same app, and it worked fine there.
I really have no idea what I'm doing wrong.
I tried twiking the code, adding or removing certain parts, but nothing seems to work.
Your problem is that in your while loop you're using dr[0] instead of orders[0]. This is trying to get the value from the SqlDataReader dr.
A good way to avoid mix-ups like this would be to create the data reader in a using block.
using (var dr = select_cmd.ExecuteReader())
{
//your code here
dr.Close();
}
then
using (var orders = select_orders.ExecuteReader())
{
// your code here
orders.Close();
}
This would prevent you from accidently referencing the wrong reader because VS would give you an error saying it doesn't exist.
Your code:
dr.Close(); //<-- dr closed
SqlDataReader orders = select_orders.ExecuteReader(); // <-- Reader is "orders" here
while (orders.Read())
{
UnfulfilledOrders CurrentOrder = new UnfulfilledOrders(Convert.ToInt32(dr[0]), Convert.ToString(dr[1]), Convert.ToString(dr[2]), Convert.ToString(dr[3]), Convert.ToInt32(dr[4]));
OrderList.Items.Add(CurrentOrder);
}
dr was closed previously, do you mean "orders" instead of "dr"?

MS Access table not refreshing correctly after inserting with c# ExecuteNonQuery

I'm having an strange behaviour when inserting records in an empty MS Access table using an external c# application
My process is:
From inside Access I execute the c# console application using a WshShell object, with 'waitOnReturn', so access waits until shell ends.
The c# just connects to the database, and executes a non query oledbCommand
When Access resumes after shell ends, I try to read the new records, but get an error: no records!. But, If I manually open the updated table, the records are there!
So, the problem is that the table does not update after inserting
This is my code in Access
Dim wsh As Object
Dim waitOnReturn As Boolean
Dim errorCode As Integer
Set wsh = CreateObject("WScript.Shell")
waitOnReturn = True
errorCode = wsh.Run("UpdateTable.exe", vbMaximizedFocus, waitOnReturn)
If errorCode <> 0 Then GoTo Error:
Dim dbf As DAO.Database
Dim UpdatedTable As DAO.Recordset
Set dbf = CurrentDb
Set UpdatedTable = dbf.OpenRecordset("MyTable", dbOpenTable)
UpdatedTable.MoveFirst 'ERROR! No records found
But records have been inserted! They are there!. In fact, when I get the error, Access stops and enter in debug mode. At this moment I manually open "MyTable" and I see the data. Then, I close the table, and resume (continue) the Access code execution, and now the records are found and code runs smooth.
The c# code for inserting records (in this example, only one record) is this:
string connectionString = "Provider=Microsoft.JET.OLEDB.4.0;data source=" + pathToMyDB;
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
OleDbCommand command = connection.CreateCommand();
command.CommandText = "INSERT INTO MyTable ([Field1], [Field2])" + " VALUES (#Param1, #Param2)";
command.Parameters.Add("#Param1", OleDbType.WChar, 35);
command.Parameters.Add("#Param2", OleDbType.Date);
command.Parameters["#Param1"].Value = "my string";
command.Parameters["#Param2"].Value = DateTime.Now;
int insertedRowsCount = 0;
using (OleDbTransaction transaction = connection.BeginTransaction())
{
command.Transaction = transaction;
try
{
insertedRowsCount = command.ExecuteNonQuery();
}
catch (InvalidOperationException queryExecutionException)
{
transaction.Rollback();
ProcessQueryExecutionExceptions(queryExecutionException);
}
if (insertedRowsCount == 1)
{
transaction.Commit();
}
else
{
transaction.Rollback();
}
}
command.Parameters.Clear();
connection.Close();
}
In Access, what could be the problem? Is there a way to force access to refresh or update the table before reading it? I have tried to close and reopen table before movefirst, inserted DoEvents after shell execution... Nothing works :(
In c#, is something wrong with the code? Should I have to change something in the connection string, or the command, or the transaction to force the update of the table?
The problem is not really a c# code issue. It is simply that the Access session is not yet aware of the new record which was added by an external process. The same thing can happen with an INSERT from any external process. I reproduced the problem with a VBScript file substituted for UpdateTable.exe
This Access VBA code triggers error 3021, "No current record" at UpdatedTable.MoveFirst ...
Dim dbf As DAO.Database
Dim UpdatedTable As DAO.Recordset
Dim wsh As Object
Dim waitOnReturn As Boolean
Dim errorCode As Integer
Set wsh = CreateObject("WScript.Shell")
waitOnReturn = True
errorCode = wsh.Run("C:\Windows\SysWOW64\cscript.exe C:\share\Access\vbscript\AdoInsert.vbs", vbMaximizedFocus, waitOnReturn)
'CreateObject("JRO.JetEngine").RefreshCache CurrentProject.Connection
Set dbf = CurrentDb
Set UpdatedTable = dbf.OpenRecordset("tblKaikus", dbOpenTable)
UpdatedTable.MoveFirst ' without RefreshCache -> ERROR 3021, "No current record."
Enabling the CreateObject("JRO.JetEngine").RefreshCache line makes the newly added record immediately available in the current Access session, so the recordset MoveFirst method does not trigger an error.

How to close all existing connections to a DB programmatically

I want to close the existing connections to an SQL Server so that I can do a restore on that database. I am using the entity framework. I tried executing
alter database YourDb
set single_user with rollback immediate
but then I get an exception saying that
Connection was not closed
I can not figure out why the connections are not allowed to close?
This image shows the full exception
this is the method,
public void dbQueueryExctr(string queuery)
{
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
connectionx.Open();
//connectionx.Open(); // Removed
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
reader = cmd.ExecuteReader();
connectionx.Close();
}
Edit:
I removed the first .Open(). Now I have only Open()
It does seem that Entity Framework keeps a connection to the database. You can see it be executing sp_who2 in SQL Server Management Studio where Entity Framework is listed as EntityFrameworkMUE under ProgramName.
You don't have to use "raw" sql statements to disconnect the active connections though, it can be solved this way as well:
Server server = new Server(".\\SQLEXPRESS");
Database database = new Database(server, dbName);
database.Refresh();
server.KillAllProcesses(dbName);
database.DatabaseOptions.UserAccess = DatabaseUserAccess.Single;
database.Alter(TerminationClause.RollbackTransactionsImmediately);
//restore.SqlRestore(server);
You get that error when you are call Open() on a connection twice. You should make all SqlConnection objects you create inside using blocks and only open them once.
If you are reusing connections "to make it faster" .NET already does that by default for you via Connection Pooling but you must dispose of the connection object to make it work.
You need to dispose the reader, the command and the connection. Your reader is not disposed. This code snippet will guarantee that the connection is closed even if there are exceptions thrown during the read process.
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "Command text.....";
using (var reader = cmd.ExecuteReader())
{
....
}
}
}
Your first problem (now that you have posted your code) is you call open twice:
public void dbQueueryExctr(string queuery)
{
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
//YOU CALL OPEN HERE
//DELETE THIS ONE!!!
connectionx.Open();
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
//AND OPEN HERE
connectionx.Open();
reader = cmd.ExecuteReader();
//You do not need connectionx.Close() here
//You have it within a using which will dispose the connection
//upon exiting the using scope.
connectionx.Close();
}
Next your problem will require you to reset the database to force close all connections. You will have to use a separate connection string to connect to MASTER not the database you are trying to close all connections to.
alter database <data base>
set offline with rollback immediate
alter database <data base>
set online with rollback immediate
Once you have executed the above SQL from MASTER against the database needing reset you should be good to do whatever you need to do. Remember, connect to master!! If you connect to the database you are trying to reset you end up closing all connections, including yourself, which will not work!
Change your Catalog to master.
Example Connection String (from MSDN):
"Persist Security Info=False;Integrated Security=true;Initial Catalog=Master;server=(local)"
Also ensure the SQL User you are using has full permissions to master. You do this by opening management studio and looking at the users collection under master.
The error is pretty clear...using Linq that way, you can't close the connection you are currently on. I haven't tried this but I think the following would work...try creating a stored procedure in your database and run it in your C# code using either a TableAdapter or SqlCommand(you can still use Linq too). Your code won't know you are about to run a stored procedure that is about to kill it's connection so it should work.
CREATE PROCEDURE [dbo].[sp_KillSpidsByDBName]
#dbname sysname = ''
AS
BEGIN
-- check the input database name
IF DATALENGTH(#dbname) = 0 OR LOWER(#dbname) = 'master' OR LOWER(#dbname) = 'msdb'
RETURN
DECLARE #sql VARCHAR(30)
DECLARE #rowCtr INT
DECLARE #killStmts TABLE (stmt VARCHAR(30))
-- find all the SPIDs for the requested db, and create KILL statements
-- for each of them in the #killStmts table variable
INSERT INTO #killStmts SELECT 'KILL ' + CONVERT (VARCHAR(25), spid)
FROM master..sysprocesses pr
INNER JOIN master..sysdatabases db
ON pr.dbid = db.dbid
WHERE db.name = #dbname
-- iterate through all the rows in #killStmts, executing each statement
SELECT #rowCtr = COUNT(1) FROM #killStmts
WHILE (#rowCtr > 0)
BEGIN
SELECT TOP(1) #sql = stmt FROM #killStmts
EXEC (#sql)
DELETE #killStmts WHERE stmt = #sql
SELECT #rowCtr = COUNT(1) FROM #killStmts
END
END
GO
Now you can run this stored procedure from code and it will kill open connections even your own. Enjoy!
It is good practice to check to see if the connection is open before attempting to open it. Try adding a check before trying to open your connection, something like this:
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
if(connectionx.State != ConnectionState.Open
connectionx.Open();
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
reader = cmd.ExecuteReader();
connectionx.Close();
}
This will help prevent the issue you described.
You can use SqlConnection.ClearAllPools and SqlConnection.ClearPool to close all or one connection in from .NET.
ClearPool clears the connection pool that is associated with the connection. If additional connections associated with connection are in use at the time of the call, they are marked appropriately and are discarded (instead of being returned to the pool) when Close is called on them.
ClearAllPools resets (or empties) the connection pool. If there are connections in use at the time of the call, they are marked appropriately and will be discarded (instead of being returned to the pool) when Close is called on them.
for examples:
using(var comm = new SqlConnection())
using(var comExecuteInsert = new SqlCommand())
{
comExecuteInsert.Connection = comm;
comExecuteInsert.CommandType = CommandType.StoredProcedure;
comExecuteInsert.CommandText = strProcedureName;
comExecuteInsert.ExecuteScalar();
comExecuteInsert.Parameters.Clear();
comm.Close();
}
SqlConnection.ClearAllPools();
Once exam this way, this is my Data access layer samples:
public T ExecuteScalar<T>(SqlCommand cmd, params SqlParameter[] Params)
{
try
{
if (Transaction != null && Transaction != default(SqlTransaction))
cmd.Transaction = Transaction;
else
cmd.Connection = SqlConn;
if (Params != null && Params.Length > 0)
{
foreach (var param in Params)
cmd.Parameters.Add(param);
}
Open();
var retVal = cmd.ExecuteScalar();
if (retVal is T)
return (T)retVal;
else if (retVal == DBNull.Value)
return default(T);
else
throw new Exception("Object returned was of the wrong type.");
}
finally
{
Close();
}
}

Should I use ExecuteNonQuery for this db backup command

I have a method that allows me to kick off a back up of a data base. What I am wondering is if I should be using ExecuteNonQuery() in this context or if there is something better to use. Here is my code currently:
public static void RunBackup(string dbName, string filePath, string backupName, string connString)
{
using(SqlConnection objConnection = new SqlConnection(connString))
{
string commmandText = "BACKUP DATABASE #DBName TO DISK = #FilePath WITH NOFORMAT, NOINIT, NAME = #BackUpName, SKIP, NOREWIND, NOUNLOAD, STATS = 10";
SqlCommand objCommand = new SqlCommand(commmandText,objConnection);
objCommand.Parameters.AddWithValue("#dbName", dbName);
objCommand.Parameters.AddWithValue("#FilePath", filePath);
objCommand.Parameters.AddWithValue("#BackUpName", backupName);
objConnection.Open();
objCommand.ExecuteNonQuery();
objConnection.Close();
}
}
The one thing I am concerned about is being able to verify that the backup is complete and successful while handling time out issues for backups that take and extended time to complete.
ExecuteNonQuery means that the command doesn't return any data. It doesn't mean that it executes asynchronously or that you won't receive error information. It will block until the command finishes and return any errors that may occur
To handle the issue of the long running query I ended up going with this:
public static void RunBackup(string dbName, string filePath, string backupName, string connString)
{
string commmandText = "BACKUP DATABASE #DBName TO DISK = #FilePath WITH NOFORMAT, NOINIT, NAME = #BackUpName, SKIP, NOREWIND, NOUNLOAD, STATS = 10";
SqlConnection objConnection = new SqlConnection(connString);
try
{
SqlCommand objCommand = new SqlCommand(commmandText, objConnection);
objCommand.Parameters.AddWithValue("#dbName", dbName);
objCommand.Parameters.AddWithValue("#FilePath", filePath);
objCommand.Parameters.AddWithValue("#BackUpName", backupName);
objConnection.Open();
IAsyncResult result = objCommand.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
System.Threading.Thread.Sleep(100);
}
int count = objCommand.EndExecuteNonQuery(result);
}
catch (SqlException e)
{
throw e;
}
finally
{
objConnection.Close();
}
}
This will allow me to execute the command without asyncronously without timeout issues. I will be adding some additional error handling etc in my final code set. I may do some additional work to see if I can get a better status returned at the end of the script that I can get via EndExecuteNonQuery or through an AsyncCallBack.
ExecuteNonQuery()
should be fine to use here. What I would do is run a try catch around the using to catch any errors that might happen and deal with them appropiately.
You should use ExecuteNonQuery when you do not what to receive any information from the database as a result of your call. If any error with happen during execute of the command you will get a corresponding exception.
This does look like the type of thing you should put in a stored procedure to do some error handling.
Also, have a look here to see it done in code.
I think ExecuteNonQuery is fine, but You should consider to user a timeout with Your query.
objCommand.CommandTimeout = 60*60; // for an hour or more
If You're using a desktop application, then for sure You should execute this query within asynchronous call.
ExecuteNonQuery is the correct command to use.
If you wish to receive more info about the restore process you should subscribe to the InfoMessage event of the SqlConnection object. That was you can capture all the "non-error" messages as well.
Try it. it resolved timeout expired problem while large size db.
Private Sub Command1_Click()
On Error Resume Next
Dim con As New Connection
Dim tm As String
con.CommandTimeout = 500'''Command timeout should be 500
With con
.ConnectionString = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=dbiBMS;Data Source=192.168.103.4"
.Open
End With
tm = CStr(Time)
con.Execute " backup database dbiBMS to disk='E:\Database_Backup\Test1.bak' with format "
con.Close
MsgBox tm
Exit Sub
x:
MsgBox Err.Description
End Sub

Categories