Database connection closure location in try catch/using - c#

Which is better to make sure that the db connection is closed if the execution fails?
try
{
using (var mySqlConnection = new MySqlConnection(DatabaseManagement.DatabaseConnectionString))
{
DatabaseManagement.DatabaseCommand = mySqlConnection.CreateCommand();
DatabaseManagement.DatabaseCommand.CommandText = "INSERT INTO lastlaptimes Values ('" + UserObject.UserName + "','" + _lastLapTime + "')";
mySqlConnection.Open();
DatabaseManagement.DatabaseCommand.ExecuteNonQuery();
}
}
catch (MySqlException exception)
{
Logger.Error(exception);
}
Or this:
using (var mySqlConnection = new MySqlConnection(DatabaseManagement.DatabaseConnectionString))
{
try
{
DatabaseManagement.DatabaseCommand = mySqlConnection.CreateCommand();
DatabaseManagement.DatabaseCommand.CommandText = "INSERT INTO lastlaptimes Values ('" + UserObject.UserName + "','" + _lastLapTime + "')";
mySqlConnection.Open();
DatabaseManagement.DatabaseCommand.ExecuteNonQuery();
}
catch (MySqlException exception)
{
mySqlConnection.Close();
Logger.Error(exception);
}
}
I'm having issue with too many connections against the db, and I'm wondering if my first approach is leading to the problem with the connections, as the code is called numerous times and a new connection is opened and fails again and increasing the connections by 1.
Thanks for any help.

The only difference between these is whether or not you are explicitly calling the Close statement (both have a using statement, which runs Dispose automatically).
So the real question here is - does Dispose close the connection or do you need to call it explicitly? I believe the answer is that Dispose will call this for you (see this question). What that means is either works well - pick whichever you favor (I suppose the first is technically one line less code...)

Related

"database is locked" C# & SQLite

I keep getting this exception over and over. I've tried separating my query into two separate queries, that didn't work. I've checked to make sure the db connection is closed elsewhere before it's opened during this method, it's definitely closed before the function is called and opened before any queries.
Below iss the code for the function. I've set breakpoints and the query itself is fine. The code is the exact same that I used previously for updating a PIN function, with just the query string changed, so I don't know why it's causing issues:
Code:
public void transferMoney(string senderIban, decimal senderBalance, string receiverIban, decimal transferAmount,string messageOptional)
{
//myBankAccount.AccountPin = updatedPin;
DataTable dtUser = new DataTable();
sqlconnConnection.Open();
string strQuery2 = #"UPDATE Accounts SET Balance = Balance + " + Convert.ToDecimal(transferAmount) + " WHERE GUID = '" + receiverIban + "';"
+ "UPDATE Accounts SET Balance = Balance - " + Convert.ToDecimal(transferAmount) + " WHERE GUID = '" + senderIban + "';";
// example of a Paramaterised SQL statement.
SQLiteCommand sqlcomCommand2 = new SQLiteCommand(strQuery2, sqlconnConnection);
SQLiteDataAdapter sqldatadptAdapter = new SQLiteDataAdapter(sqlcomCommand2); // local SQL data Adaptor
try
{
// sqldatadptAdapter.Fill(dtUser);
sqlcomCommand2.ExecuteNonQuery();
}
catch (Exception ex)
{
// Exception will the "thrown" when there was a problem
throw new Exception($"UPDATE WAS unsuccessful:\n{ex.Message}");
}
finally
{
sqlconnConnection.Close();
}
Maybe you have a DB browser opened? Or you have accessed the DB some other way. This error only occurs when DB is modified or used elsewhere. If you can't find it, I'd suggest restarting PC just in case there something hidden :)
P.S. Posting this as answer as I cannot comment under the question for technical reasons :)

SQL Server : "require open and available connection"

I'm just learning databases to store a (large amount) of user entry data.
I have the following code, which checks a record and chooses whether to update or create new
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sc1 = #"select count(*) from job1 where report = #report";
SqlCommand check = new SqlCommand(sc1, connection);
check.Parameters.AddWithValue("#report", jname);
// check if the report number already exists, if not make a new table otherwise insert
int test = (int)check.ExecuteScalar();
if (test > 0)
{
jobCardExistingTable(connection);
digCardExistingTable(connection);
//insert into existing table code
}
If I use either jobCardExistingTable or digCardExisting table, they work fine. If I use both, I get the error
require open and available connection
I assume that the first ExecuteNonQuery (which are contained in the jobCard and digCard methods) is doing something with the connection - can I keep this one open, or do I have to open a new one each time I call a method? Maybe I'm doing this all wrong anyways...each method is calling a new table in the database, should I be calling them all at once?
Edit: part of the issue is jobCardTable (digCardTable is identical, just a different query)
public void jobCardNewTable(SqlConnection connection)
{
using (connection)
{
string sc3 = "";
sc3 = #"INSERT INTO job1 (" + pv.jobstring + ") VALUES (" + pv.jobparam + ")";
SqlCommand cmd = new SqlCommand(sc3, connection);
queryParams(cmd, 0);
cmd.ExecuteNonQuery();
}
}
Edit: solved - realised that using{} disposes the connection. Took all the using{} out of the methods, and used a single using{} to encompass all the method calls and it works
You should not use using (connection) if you are using same connection in other part of code. using dispose connection and make unavailable for further connection.
So, your jobCardNewTable method implementation should be without using statement :
public void jobCardNewTable(SqlConnection connection)
{
string sc3 = "";
sc3 = #"INSERT INTO job1 (" + pv.jobstring + ") VALUES (" + pv.jobparam + ")";
SqlCommand cmd = new SqlCommand(sc3, connection);
queryParams(cmd, 0);
cmd.ExecuteNonQuery();
}
I would recommend to create new connection whenever you need it and dispose it.

How to restore SQL Server backups using asp.net and C#?

How to restore SQL Server backup using C#?
try
{
string test = "D:\\backupdb\\05012017_130700.Bak";
sqlcmd = new SqlCommand("Restore database EmpolyeeTable from disk='D:\\backupdb\\05012017_130700.Bak'", con);
sqlcmd.ExecuteNonQuery();
Response.Write("restore database successfully");
}
catch (Exception ex)
{
Response.Write("Error During backup database!");
}
Quite weird requerement you have right there. I´ve never heard of someone restoring a database backup from a webpage, and as #Alex K. told, it would be quite rare that the user that uses your web application have the required previleges.
Anyway, supposing that everything told above is OK, the code to restore a backup would be this:
Use this:
using System.Data;
using System.Data.SqlClient;
Code:
private void TakeBackup()
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
try
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "RESTORE DATABASE AdventureWorks FROM DISK = 'C:\AdventureWorks.BAK' WITH REPLACE GO";
command.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
}
This is going to work specifically for the problem you posted. Be sure to set all the parameters of your database server on the connection string, it seems from the comments on your question that you are having communication issues. You have to solve that problems before you do anything. Some tips for that:
Be sure you set all the parameters on connection string the right way
Try to connect using another tool like ODBC so you can test all parameters
Check out SQL Network settings to see if TCP/IP is enabled

Getting timeout errors with SqlTransaction on same table

public TransImport()
{
ConnString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
SqlConnection conn_new;
SqlCommand command_serial_new;
SqlConnection conn;
SqlCommand command_serial;
SqlTransaction InsertUpdateSerialNumbers;
conn = new SqlConnection(ConnString);
command_serial = conn.CreateCommand();
conn_new = new SqlConnection(ConnString);
command_serial_new = conn_new.CreateCommand();
command_serial_new.CommandText = "SELECT 1 FROM YSL00 WHERE SERLNMBR = #slnr";
var p = new SqlParameter("#slnr", SqlDbType.NVarChar, 50);
command_serial_new.Parameters.Add(p);
//Here you will start reading flat file to get serialnumber.
InsertUpdateSerialNumbers = conn.BeginTransaction();
while (!headerFileReader.EndOfStream)
{
headerRow = headerFileReader.ReadLine();
if (CheckSerialNumber(headerFields[0].Trim()))
DisplayMessage("Good serialnumber"); //this function is not copied here.
}
InsertUpdateSerialNumbers.Commit();
}
private Boolean CheckSerialNumber(string SerialNumber)
{
command_serial_new.Parameters["#slnr"].Value = SerialNumber;
try
{
var itExists = Convert.ToInt32(command_serial_new.ExecuteScalar()) > 0;
if (!itExists)
{
command_serial.Transaction = InsertUpdateSerialNumbers;
command_serial.CommandText = "INSERT INTO YSL00([Manifest_Number],[PONUMBER],[ITEMNMBR],[SERLNMBR]"
+ "VALUES ('" + Manifest + "','" + PONr + "','" + itemNumber + "','" + serialNr + "')";
var insertStatus = command_serial.ExecuteNonQuery();
return true;
}
}
catch (Exception ex)
{
LogException(ex, "Error in CheckSerialNumber =>"+ command_serial_new.CommandText.ToString());
}
return false;
}
I get error "Timeout expired. The timeout period elapsed prior to completion of the operation or server is not responding".
The CheckSerialNumber function also does an insert to YSL00 (the same table where I had executescalar. See code above).
As I mentioned earlier there are 1000s of line in a flat file that I read and update YSL000 table.
Note that I have two separate sqlcommands and also two separate connections to handle this. Reason is with sqltransaction it doesn't let me to query on the same table. I think timeout may be happening because of this?
Thanks for reading. Please suggest
Update 1: Since I have not pasted entire code, I want to mention that dispose is done using below code in the program.
if (conn != null)
{
conn.Close();
conn.Dispose();
}
if (conn_new != null)
{
conn_new.Close();
conn_new.Dispose();
}
you can increase the time out of your SqlConnection object.
you can do this with your ConnString:
string connStr = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated
Security=SSPI;Connection Timeout=300";
I think default isolation level - read commited - is preventing your 'CheckSerialNumber' method from being effective. Command_serial_new will not take into consideration rows inserted in your loop - this might lead to some troubles. To be honest I would also look for some deadlock. Perhaps command_serial_new is actually completely blocked by the other transaction.
To start off:
Set command_serial_new query as:
SELECT 1 FROM YSL00 WITH (NOLOCK) WHERE SERLNMBR = #slnr
Think about using lower isolation level to query inserted rows as well (set it to read uncommited).
Close your connections and transactions.
Use just one SqlConnection - you don't need two of them.
Many of the objects you are using implement IDisposable, and you should be wrapping them with using statements. Without these using statements, .NET won't necessarily get rid of your objects until an undetermined time when the garbage collector runs, and could block subsequent queries if it's still holding a transaction open somewhere.
So for example, you'll need to wrap your connections with using statements:
using (conn_new = new SqlConnection(ConnString)) {
...
If I am not mistaken you need to merge the file content with the table content.
For this purpose I would recommend you
Copy the file content in to a temporary table (see temporary tables and BulkInsert)
Use command MERGE (http://msdn.microsoft.com/en-us/library/bb510625.aspx) to merge the temporary table content with the original table

ExecuteNonQuery() not saving any record

I'm working a WinForms based C# tool which has an attached MDF file based database. I'm trying to use the SqlCommand.ExecuteNonQuery() method to save a record to this attached MDF database, but the record is not saved. No error or exception occurs; only problem is that the record is not actually saved.
I have a Console.WriteLine at the top which shows the query I'm trying to run. Its correct syntax-wise, and if I copy-paste it from the output windows and run it separately, it works.
I have correctly defined the connection string as the following, and it works fine for fetching records:
public static String connectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\TestBuildDB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
Here the function I'm using to save records:
public static void PerformDBWriteTransaction(string inputSQLStatement)
{
Console.WriteLine(inputSQLStatement);
DataTable returnDataTable = new DataTable();
SqlConnection sqlConnection = new SqlConnection();
sqlConnection.ConnectionString = connectionString;
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = inputSQLStatement;
cmd.Connection.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
errorMessages.Clear();
errorMessages.Append("The following errors were found in the SQL statement:\n\n");
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
MessageBox.Show(errorMessages.ToString());
}
finally
{
cmd.Connection.Close();
}
}
Can someone tell me what might be the problem ? Do I need to perform a 'commit' somehow ?
EDIT:
I have found the problem, and have written up a solution below .. Thanks to all who helped me out though :)
I found the problem ! It was very simple, and it was stupid really :) .. The code above is all correct .. Yes, people pointed out optimizations, etc, but still the code above was correct.
The problem was that when I imported the TestDB.MDF file into my Visual 2010 project, a copy of that was made inside the project's folder. When you run/debug the program, another copy of the this file is made and is put in the \bin\Debug\ folder. In the connection string I was using, I had mentioned: AttachDbFilename=|DataDirectory|\TestBuildDB.mdf .. This meant that all reads/writes were done to the copy in the bin\Debug folder. However, the TestDB.MDF file I was looking into to verify if records were inserted or not, was in the project's folder ! So basically, there were two MDF files, and I was writing the records into one file, but was trying to find them in the other :)
When you add an MDF file into your VS2010 Project, VS2010 by default makes a connection to that MDF file, from where you can browse the stuff in that MDF file .. The MDF file used for this purpose was the one placed in the project's folder, NOT the one in bin\Debug\ folder. And like I said earlier, my code used the one in the bin\Debug folder :)
So what I've done now is that I've removed the Test.MDF file reference from my project, which removes the copy present in the project's folder. However, I DO have a copy of TestDB.MDF file in the bin\Debug\ folder, which I connect to from within my application. And if I want to browse the MDf file outside my project, I use SQL Management Studio. The only problem here is that an MDF file can only be used by one program at a given time. So if I have to use it with my application, I have to take it offline from SQL Management studio, and vica versa !
I hope this explanation helps someone out there :)
The solution to this problem is very simple just give the full path of the original MDF file in the connection String like this:
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=**C:\VISUAL STUDIO 2012\PROJECTS\ENGLISHTOHINDIDICTIONARY\ENGLISHTOHINDIDICTIONARY\DICTIONARY.MDF**;Initial Catalog=Dictionary;Integrated Security=false"
providerName="System.Data.SqlClient"
That's it, your problem is solved.
I had the same challenge, I simply changed the database property "Copy to Output Directory" from "Copy always" to "Do not copy" then moved my database.mdf (drag & drop from my IDE) into the bin\debug folder.
Tip:
The bin directory is normally hidden, use the "Show All Files" to display it
Provide a catch clause for all Exceptions. If there something wrong other than SqlException, you will never see what is it and your db will neved be updated. Imagine there is a FormatException...
Also check the return of ExecuteNonQuery : it's the number of rows affected by the query.
First, you should always wrap up your IDisposable objects in a using to ensure they're closed and disposed of properly (and that connection pooling can do its thing). Second, when modifying data wrap up your sql in a transaction to maintain data integrity.
Try the following code and see if any exceptions are raised. I wouldn't normally recommend catching Exception as it's too general, I'd let that bubble up to the calling mechanism and handle it there - but for this instance it will show you any and all issues. I think your particular issue is at the .Open stage of the connection, so try stepping through.
public static void PerformDBWriteTransaction(string inputSQLStatement)
{
DataTable returnDataTable = new DataTable();
try
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlTransaction sqlTrans = sqlConnection.BeginTransaction())
{
try
{
using (SqlCommand cmd = new SqlCommand(inputSQLStatement, sqlConnection))
{
cmd.CommandType = CommandType.Text;
cmd.Transaction = sqlTrans;
cmd.ExecuteNonQuery();
}
}
catch (SqlException sqlEx)
{
sqlTrans.Rollback();
throw sqlEx;
}
sqlTrans.Commit();
}
}
}
catch (Exception ex)
{
errorMessages.Clear();
errorMessages.Append("The following errors were found in the SQL statement:\n\n");
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
MessageBox.Show(errorMessages.ToString());
}
}
Hi I am working on library database when I add student record executionNonQuery
shows error like invalid column name page opens but saving data from not happening.
Here I have given the code statement
public partial class add_student_info : Form
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-SPT6GLG\SQLEXPRESS;Initial Catalog=library_managment;Integrated Security=True;Pooling=False");
public add_student_info()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "insert into student_info values('" + textBox1.Text + "','" + textBox2.Text + "','" + textBox3.Text + "','" + textBox4.Text + "'," + textBox5.Text + "," + textBox6.Text + "," + textBox7.Text + ")";
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Student recorc addedd sussfully");
}
}
}

Categories

Resources