I get this error:
There is already an open DataReader associated with this Command which must be closed first
This is my code :
String sql_get_completed_tasks = "select * from tasks where Ending_date is not null order by Ending_date asc";
SqlCommand command_get_completed_tasks_ = new SqlCommand(sql_get_completed_tasks, cn);
SqlDataReader reader = command_get_completed_tasks_.ExecuteReader();
while (reader.Read())
{
String sql_insert_completed_tasks_toTheNewTable = "insert into history_of_tasks_achievements values ("+
reader[1] +" , N'"+ reader[2]+"' , #image , N'"+ reader[4] +"' , N'"+reader[5]+"' , N'"+ reader[6]+"' , "+
reader[7] +" , N'"+reader[8]+"' , N'"+reader[9] +"' , "+reader[10]+" , #start_date , #end_date , "+reader[13]+
")";
SqlCommand com_insert_completed_tasks_toTheNewTable = new SqlCommand(sql_insert_completed_tasks_toTheNewTable, cn);
com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("#image", reader[3]));
com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("#start_date", reader[11]));
com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("#end_date", reader[12]));
com_insert_completed_tasks_toTheNewTable.ExecuteNonQuery();
} // end of while loop
reader.Close();
MessageBox.Show("Done");
To skip this error, can I create pause or close for SqlDataReader, then re-open from the break values? What is the best solution?
That should really just be 1 statement, there is no need to iterate over the results from the select just to push them back to the same database using an insert.
const string sqlInsert =
#"INSERT INTO [history_of_tasks_achievements] (col1, col2, col3, ...)
SELECT col1, col2, col3, ... FROM [tasks] WHERE [Ending_date] IS NOT NULL ORDER BY [Ending_date] ASC";
using(var con = new SqlConnection("connection string here"))
using(var command = new SqlCommand(sqlInsert, con))
{
con.Open();
var inserted = command.ExecuteNonQuery();
}
Be sure to align the columns between the SELECT and the INSERT so they match.
In this case you can use the using statement.
// set up connection, command
using (var reader = command_get_completed_tasks_.ExecuteReader())
{
// do the reader stuff
reader.Close();
}
// Done
Related
I want to insert email in Table with only one column. I tried on 2 way. First time I tried with commandText and second time I tried with parapeters. But the both solution give me the same error.
System.Data.OleDb.OleDbException: 'Syntax error in INSERT INTO statement.'
I don't see any error in INSERT STATEMENT. Maybe the problem is in TABLE?
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT COUNT (email) FROM [User] WHERE [email] LIKE '" + userEmail + "';";
conn.Open();
int count = Convert.ToInt32(cmd.ExecuteScalar()); // This passed
if (count == 0)
{
string query = #"INSERT INTO User (email) VALUES (#email)";
string cmdText= #"INSERT INTO User (email) VALUES ('"+userEmail+"')";
OleDbCommand command = new OleDbCommand(cmdText, conn);
// command.Parameters.AddWithValue("#email", "userEmail");
// command.CommandText = query;
command.ExecuteNonQuery(); // I GOT ERROR HERE
}
conn.Close();
}
User is a keyword. You should INSERT INTO [USER] instead
string cmdText= #"INSERT INTO User (email)) VALUES ('"+userEmail+"')";
you have one ')' too many after (email)
I'm getting a syntax error in INSERT INTO statement and I can't figure out why. I've checked several different SO questions that were almost exactly the same as my problem and after changing my code this way and that way it still isn't working.
var cnnStr = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};", oldDb);
var cnn = new OleDbConnection(cnnStr);
cnn.Open();
//make new access table
using (OleDbCommand command = new OleDbCommand())
{
command.Connection = cnn;
command.CommandText = String.Format("CREATE TABLE [{0}] ([Tag] string, [Text] string)", newTable + "_Diff");
try
{
command.ExecuteNonQuery();
}
catch
{
//table already exists
}
}
//fill access table
using (OleDbCommand command = new OleDbCommand())
{
command.Connection = cnn;
command.CommandText = String.Format("INSERT INTO [{0}] (Tag, Text) VALUES (?, ?)", newTable + "_Diff");
command.Parameters.Add(new OleDbParameter("Tag", ""));
command.Parameters.Add(new OleDbParameter("Text", ""));
for (int i = 0; i < (diffText.Length - 1); i++)
{
command.Parameters["Tag"].Value = diffTag[i];
command.Parameters["Text"].Value = diffText[i];
command.ExecuteNonQuery();
}
}
cnn.Close();
Creating the table is working so I know there's not a problem with my connection, there's just something it doesn't like about my insert statement.
In your insert command put text inside a square bracket, "text" is a keyword
command.CommandText = String.Format("INSERT INTO [{0}] (Tag, [Text])
VALUES (?, ?)", newTable + "_Diff");
also make sure you are including your values with single quote
values ('?','?')
hope this works
I have two tables, one containing names, and one containing rates and other data that is lined to each name. After I insert a new name into table A, I want to get the newly auto generated PK to now use to insert into my other table B with rates.
How can I do this? I read about scope_identity online but I'm not sure how to use it.
This is what I have so far:
SqlConnection con = new SqlConnection(pubvar.x);
SqlCommand command = con.CreateCommand();
command.CommandText ="Insert into A values('" +Name + "')";
SqlCommand command2 = con.CreateCommand();
command2.CommandText = "Insert into B values(....)";
SELECT SCOPE_IDENTITY();
con.Open();
command.ExecuteNonQuery();
con.Close();
Considering the case you've described, I don't see any need to return the identity from the database. You can simply issue both statements in one command:
using (var cnx = new SqlConnection(pubvar.x))
using (var cmd = new SqlCommand
{
Connection = cnx,
CommandText = #"
insert into A (Name) values (#name)
insert into B (A_ID, Rate) values (scope_identity(), #rate)
",
Parameters =
{
new SqlParameter("#name", name),
new SqlParameter("#rate", .5m) //sample rate
}
})
{
cnx.Open();
cmd.ExecuteNonQuery();
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Barcode
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string strconn = #"Data Source=ASHWINI-LAPY\SQLEXPRESS;Initial Catalog=complete;Integrated Security=True;Pooling=False";
SqlDataReader reader = null;
SqlConnection conn = null;
conn = new SqlConnection(strconn);
conn.Open();
DateTime Dt_Time = DateTime.Now;
string Barcode = textBox1.Text;
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
reader = cmd.ExecuteReader();
if (reader != null && reader.HasRows)
{
//email exists in db do something
MessageBox.Show("Barcode Already Exists!!");
}
else
{
string strquery = string.Format("insert into table3 values('{0}','{1}')", Barcode, Dt_Time);
cmd = new SqlCommand(strquery, conn);
int count = (int)cmd.ExecuteNonQuery();
MessageBox.Show("Barcode:" + Barcode +
"\nTime" + Dt_Time);
}
I am new to C# coding so I tried to do it like what I mentioned below in code, so please somebody help me.
I want to insert a barcode manually and when I press button the SQL Server database has to be checked whether that barcode exists. If not, it has to insert that barcode into the database, but if it already exists, it has to give a message that barcode already exists!
Along with inserting barcode I am also inserting system date and time also in database.
EDIT
C# code that you can write in your button click event
using (System.Data.SqlClient.SqlConnection cn =
new System.Data.SqlClient.SqlConnection(#"Data Source=ASHWINI-LAPY\SQLEXPRESS;Initial Catalog=complete;Integrated Security=True;Pooling=False"+
"Integrated Security=True"))
{
using (System.Data.SqlClient.SqlCommand cmd= new System.Data.SqlClient.SqlCommand("IsBarcodeCheckAndInsert", cn))
{
cmd.CommandType=CommandType.StoredProcedure ;
SqlParameter parm= new SqlParameter("#BarCode", cn",SqlDbType.VarChar) ;
parm.Value="ALFKI";
parm.Size=25;
parm.Direction =ParameterDirection.Input ;
cmd.Parameters.Add(parm);
SqlParameter parm2=new SqlParameter("#IsExists",SqlDbType.Int);
parm2.Direction=ParameterDirection.Output;
cmd.Parameters.Add(parm2);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
int IsExists = Convert.ToInt32(cmd.Parameters["#IsExists"].Value.ToString());
if(IsExists ==0)
MessageBox.Show("Barcode Already Exists !!");
else if(IsExists ==1)
MessageBox.Show("Barcode not Exists And Inserted In DataBase!!");
}
}
SQL Procdure
CREATE PROCEDURE [dbo].[IsBarcodeCheckAndInsert]
(
#BarCode AS VARCHAR(25),
#IsExists AS INT out )
AS
BEGIN
IF EXISTS (SELECT * FROM table3 WHERE BarCode = #BarCode )
BEGIN
set #IsExists =1
END
ELSE
BEGIN
Insert into table3 values(#BarCode ,getDate())
set #IsExists =0
END
END
Whats wrong with the code I check your code code is fine ..if it's not working at you end what error you are getting.
Just on recommandation make use of SQLParameter in your second queryi.e in insert query also to avoid SQLInjection attack for more detail check here : How does SQLParameter prevent SQL Injection?
Check out these lines of code:
string Barcode = textBox1.Text;
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
If textBox1.Text is equal to "example", the resulting SQL query would be
Select Barcode from table3 where 'example'='example'
You might want to change the SqlCommand statement to:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode=#Barcode", conn);
You can do something like this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode=#Barcode", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Regards
You mixed up your sql parameters syntax, this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Should be changed to be like this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode = #Barcode", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Basically you switched the column name with the parameter name in the query.
UPDATE
As for the "There is already an open DataReader..." exception, adjust the code with using blocks (in a "best practice" approach), like this:
private void button1_Click(object sender, EventArgs e)
{
string strconn = "<connection string";
using (SqlConnection conn = new SqlConnection(strconn))
{
bool readerHasRows = false; // <-- Initialize bool here for later use
DateTime Dt_Time = DateTime.Now;
string Barcode = textBox1.Text;
string commandQuery = "SELECT Barcode FROM table3 WHERE Barcode = #Barcode";
using(SqlCommand cmd = new SqlCommand(commandQuery, conn))
{
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
using(SqlDataReader reader = cmd.ExecuteReader())
{
// bool initialized above is set here
readerHasRows = (reader != null && reader.HasRows);
}
}
if (readerHasRows)
{
//email exists in db do something
MessageBox.Show("Barcode Already Exists!!");
}
else
{
//Same as above
string strquery = "INSERT INTO table3 VALUES (#Barcode, #DtTime)"; // '{0}','{1}')", Barcode, Dt_Time);
using (SqlCommand cmd = new SqlCommand(strquery, conn))
{
cmd.Parameters.AddWithValue("Barcode", Barcode);
cmd.Parameters.AddWithValue("DtTime", Dt_Time);
int count = cmd.ExecuteNonQuery(); // this already the number of affected rows by itself
// NOTE: '\n' doesn't really work to output a line break.
// Environment.NewLine should be used.
MessageBox.Show("Barcode:" + Barcode + Environment.NewLine + "Time" + Dt_Time);
}
// code probably goes on ...
} // end of using(SqlConnection...
} // end of method
Should at least lead you on the right track.
You can do this in one sql query with the Merge-command.
In plain SQL it will look like:
merge table3 WITH(HOLDLOCK) as target
using (SELECT #Barcode, #DtTime)
as source (Barcode, DtTime)
on target.Barcode = #Barcode
when not matched then
insert ( Barcode, DtTime)
values ( #Barcode, #DtTime);
i m trying to retrieve the Specialization ID from a table called Specializationtbl, using C# MSVS 2008 and the table includes SpecializationName and SpecializationID beside some other rows and my question is related to some error " No Data to present ", the command goes as bellow:
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
DBcnction.Open();
SqlDataReader ReadSpecID_ = READSpecID.ExecuteReader();
ReadSpecID_.Read();
int SpecID_ = Convert.ToInt16(ReadSpecID_["SpecID"].ToString());
DBcnction.Close();
i also tried to Select the "SpecID" instead of all the rows, but cant seem to seal the query correctly and keep receiving "No data present " error, any idea where am i making the mistake?
1) Try opening DBcnction before assigning the value to READSPecID
DBcnction.Open();
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
2) Run the command in SSMS:
SELECT * FROM Specializationtbl WHERE SpecializationName ='yourvalue'
and see if any results are returned
3) Check comboBox1.Text has a value in it
4) Validate the contents of comboBox1.Text (Or use paremetrised queries or a stored procedure) to ensure you do not become a victim of SQL Injection: http://en.wikipedia.org/wiki/SQL_injection
Refactor to solve your TWO problems:
Your SQL injection problem when building your SQL statement.
Use ExecuteScalar if you only need one value.
Implement using blocks.
string retVal;
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
retVal = cmd.ExecuteScalar().ToString();
}
int specID = int.Parse(retVal);
If you really needed more than one value from your statement:
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID, Value2 FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
var dr = cmd.ExecuteReader();
while (dr.Read())
{
Customer c = new Customer {
ID = dr["SpecID"].ToString(),
Value = dr["Value2"].ToString(),
};
}
}
Need to first test if there are any rows. I suspect the query is returning zero rows.
if (ReadSpecID_.HasRows)
{
ReadSpecID_.Read();
}