I have a very slow sql transaction, which inserts new rows in the table. All other "select" queries from another connections wait for this transction to unlock the table.
Is it posible to fetch old rows from the table, while the first transaction works?
SqlExpress 2008 R2.
For exapmle:
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(
delegate()
{
var conn = new SqlConnection(#"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******");
conn.Open();
var cmd = conn.CreateCommand();
var tr = conn.BeginTransaction( IsolationLevel.RepeatableRead, "test");
cmd.Transaction = tr;
cmd.CommandText = #"INSERT INTO Cards (SerialNumber,OperationID,TariffID,RequestTime,State,AgentInfo) VALUES('1213','345',13, GETDATE(),1,'')";
cmd.ExecuteNonQuery();
//very slow transaction
System.Threading.Thread.Sleep(300000);
tr.Commit();
conn.Close();
});
t.Start();
}
private void button2_Click(object sender, EventArgs e)
{
var conn = new SqlConnection(#"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******");
conn.Open();
var cmd = conn.CreateCommand();
var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test2");
cmd.Transaction = tr;
cmd.CommandText = #"SELECT COUNT(*) FROM Cards";
var r = cmd.ExecuteReader();
r.Read();
r.Close();
tr.Commit();
conn.Close();
}
button2_Click method doesnt't fetch a row immidiately, it waits for commit in I have a very slow sql transaction, which inserts new rows in the table. All other "select" queries from another connections wait for this transction to unlock the table.
Is it posible to fetch old rows from the table, while the first transaction works?
SqlExpress 2008 R2.
For exapmle:
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(
delegate()
{
var conn = new SqlConnection(#"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******");
conn.Open();
var cmd = conn.CreateCommand();
var tr = conn.BeginTransaction( IsolationLevel.RepeatableRead, "test");
cmd.Transaction = tr;
cmd.CommandText = #"INSERT INTO Cards (SerialNumber,OperationID,TariffID,RequestTime,State,AgentInfo) VALUES('1213','345',13, GETDATE(),1,'')";
cmd.ExecuteNonQuery();
//very slow transaction
System.Threading.Thread.Sleep(300000);
tr.Commit();
conn.Close();
});
t.Start();
}
private void button2_Click(object sender, EventArgs e)
{
var conn = new SqlConnection(#"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******");
conn.Open();
var cmd = conn.CreateCommand();
var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test2");
cmd.Transaction = tr;
cmd.CommandText = #"SELECT COUNT(*) FROM Cards";
var r = cmd.ExecuteReader();
r.Read();
r.Close();
tr.Commit();
conn.Close();
}
button2_Click method doesnt't fetch a row immidiately, it waits for commit in button1_Click thread.
One quick 'get out of jail' card is enabling read committed snapshot on the database, see Choosing Row Versioning-based Isolation Levels, also mentioned in Deadlocked!. When RCSI is enabled on the database your butonn2 click read will do exactly what you want: it will read an old version of the row, w/o waiting for button1 to commit.
To enable RCSI simply run this once:
ALTER DATABASE [test] SET READ_COMMITTED_SNAPSHOT ON;
Of course there is no free lunch: enabling row-versioning will occur a cost in tempdb IO and size. See Row Versioning Resource Usage. For an Express instance there will be no measurable impact.
Related
I am getting following error
;expected
I am trying to find sum of column values in my webform.
protected void Page_Load(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select SUM("AMOUNT DEPOSITED ") From MAIN_TABLE6";
Double amount = cmd.ExecuteScalar();
Label3.Text = amount.ToString();
}
Use brackets to enclose your columns in SQL Server.
protected void Page_Load(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select SUM([AMOUNT DEPOSITED]) From MAIN_TABLE6";
Double amount = cmd.ExecuteScalar();
Label3.Text = amount.ToString();
}
I update-voted the answer by #ϻᴇᴛᴀʟ because he solved the problem with the brackets. However I like to see that database objects are closed and disposed. If database objects are kept local to the methods where they are used then using blocks accomplish this even if there is and error.
It is possible to pass the connection string directly to the constructor of the connection and pass the command text and connection to the constructor of the command. CommandType.Text is the default value so it is not necessary to set it.
I have opened the connection directly before the .Execute... and it is closed immediately after. The user interface is not updated until the connection is closed.
protected void Page_Load(object sender, EventArgs e)
{
double amount;
using (SqlConnection con = new SqlConnection("Your connection string"))
using (SqlCommand cmd = new SqlCommand("Select SUM([AMOUNT DEPOSITED]) From MAIN_TABLE6;", con))
{
con.Open();
amount = (double)cmd.ExecuteScalar();
}
Label3.Text = amount.ToString();
}
The actual issue is not this - "Conversion failed when converting from a character string to uniqueidentifier" but the issue is that, the transaction doesn't get rolled back after you hit the issue.
My code here,
var connectionstring = "Server= ****; Database= ****; Integrated Security=True;";
var errorInformation = new List<string>();
using (SqlConnection objConn = new SqlConnection(connectionstring))
{
objConn.Open();
var objTrans = objConn.BeginTransaction(); // Begins here
var sql = $"insert into tblProject values('7', 'TestProject')";
SqlCommand insertCommand = new SqlCommand(sql, objConn, objTrans);
try
{
insertCommand.ExecuteNonQuery();
// ProjectID is a unique Identifier in database
SqlCommand cmd = new SqlCommand("SELECT * FROM SOMEOTHERTABLE WHERE PROJECTID=''", objConn, objTrans);
cmd.CommandType = CommandType.Text;
var dataTable = new DataTable("SomeTableName");
using (var adapter = new SqlDataAdapter(cmd))
{
var dt = adapter.Fill(dataTable); // Exception happens here
}
objTrans.Commit(); // Commit here
}
catch (Exception ex)
{
errorInformation.Add(ex.Message);
}
var sql1 = $"insert into tblProject values('8', 'TestProject')";
SqlCommand objCmd2 = new SqlCommand(sql1, objConn, objTrans);
objCmd2.ExecuteNonQuery();
if (errorInformation.Any())
{
objTrans.Rollback(); // Rollback here
}
}
The query that gets executed after the exception, using the same connection object will not rollback. This is a bug that Microsoft needs to look into. Otherwise their rollback feature is not reliable.
I would expect either my second insert command to fail or my rollback to be successful.
In my table there is one XML column. I want to fetch the XML data in one textbox and make some corrections and update it:
private void button2_Click(object sender, EventArgs e)
{
con.Open();
string str = "select C1 from TableName where C2='" + txt1.Text+ "'";
SqlCommand cmd1 = new SqlCommand(str, con);
XmlReader xml = cmd1.ExecuteXmlReader();
xml.Read();
txt2.Text = xml.ReadOuterXml();
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml(txt2.Text);
}
Now I want to make some changes and update it in my database. When I try to change in textbox it does not work. How can I make changes and update in database? Please help
Update Like this
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "Update TableName set C1 = #C1 where C2 = #C2 ";
command.Parameters.AddWithValue("#C1", Textbox2.Text);
command.Parameters.AddWithValue("#C2", Textbox1.text);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
in my form I'm using a combo box to be able to select a record from the database, and then populate text boxes. Whenever I add a record (or update, delete) the combobox doesn't get the updated data until I close and rerun the program. The combobox is databound via the design view. Basically I require this combobox to update in real-time when I change the data in the table. Appreciate any help, thanks.
C# - Visual Studio 2010
Code:
//Form load
private void Technician_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'technicianDataset.Technician' table. You can move, or remove it, as needed.
this.technicianTableAdapter.Fill(this.technicianDataset.Technician);
}
private void cmo_User_SelectedIndexChanged(object sender, EventArgs e)
{
using (SqlCeConnection connection = new SqlCeConnection(#"Data Source=C:\\temp\\Project\\WindowsFormsApplication2\\database.sdf"))
{
try
{
connection.Open();
string sqlText = "SELECT User_ID, Name, Password FROM Technician WHERE User_ID = #User_ID;";
SqlCeCommand command = new SqlCeCommand(sqlText, connection);
command.Parameters.AddWithValue("#User_ID", Convert.ToInt32(cmo_User.SelectedValue));
SqlCeDataReader reader = command.ExecuteReader();
while (reader.Read())
{
txt_userID.Text = reader["User_ID"].ToString();
txt_name.Text = reader["Name"].ToString();
txt_password.Text = reader["Password"].ToString();
}
reader.Close();
connection.Close();
} catch(SqlCeException exp){
Console.Write(exp.ToString());
}
}
}
//Add Record
using (SqlCeConnection connection = new SqlCeConnection(#"DataSource=C:\\temp\\Project\\WindowsFormsApplication2\\OrkneyCheese.sdf"))
{
connection.Open();
string sqlText = "INSERT INTO Technician VALUES (#userid, #name, #password);";
SqlCeCommand command = new SqlCeCommand(sqlText, connection);
command.Parameters.AddWithValue("#name", txt_name.Text);
command.Parameters.AddWithValue("#password", txt_password.Text);
command.Parameters.AddWithValue("#userid", Convert.ToInt32(txt_userID.Text));
command.ExecuteNonQuery();
connection.Close();
cmo_User.Update();
lbl_feedbackTech.Text = "User Successfully added";
}
}
I want to delplay the row in the richtextbox
private void button1_Click(object sender, EventArgs e) {
SqlConnection con = new SqlConnection("Data Source=MOSTAFA\\SQLEXPRESS;Initial Catalog=company;Integrated Security=True");
SqlCommand com = new SqlCommand("select * from data where id='"+textBox1.Text+"')",con);
con.Open();
SqlDataReader read = com.ExecuteReader();
if (read.Read())
richTextBox1.Text = "id" + read[0].ToString();
else
label3.Text=("The client didn't found");
}
There's an error in your generated query. You have a closing parenthesis without an opening one. The line as you have it would produce:
select * from data where id='sometest')
which will yield a syntax error from SQL Server.
Try this instead:
SqlCommand com = new SqlCommand("select * from data where id='"+textBox1.Text+"'",con);
You have an extra parenthesis in that SQL statement.
But more importantly, you are leaving yourself wide open for SQL Injection. To get around this devastating and easily avoidable issue is to use parameterized queries.