Incorrect syntax near '(' when updating record in database - c#

My code is producing an Incorrect syntax near '(' exception. I have tried two different ways but they both produce the same exception. I am trying to update a record in the database.
Here is my code and the line that produces the exception is the Execute non query line. The updater.Fill(dtable) which is commented out also produces the same exception.
protected void btnSave_Click(object sender, EventArgs e)
{
int found = 0; // No match found so far
// Get the current selected Manufacturer
string currentManufacturer = grdManufact.SelectedRow.Cells[1].Text;
string currentIsModerated = grdManufact.SelectedRow.Cells[3].Text;
// Connect to the database
string strConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString2"].ToString();
SqlConnection conn = new SqlConnection(strConnectionString);
conn.Open();
// Try to find if new record would be a duplicate of an existing database record
if (txtManufactureName.Text != currentManufacturer)
{
string findrecord = "SELECT * From VehicleManufacturer WHERE ManufacturerName = '" + txtManufactureName.Text + "'";
SqlDataAdapter adpt = new SqlDataAdapter(findrecord, conn);
DataTable dt = new DataTable();
found = adpt.Fill(dt);
}
if (found == 0) // New record is not a duplicate you can proceed with record update
{
String query;
if (checkBoxModerated.Checked)
{
query = "UPDATE VehicleManufacturer (ManufacturerName, ManufacturerDescription, Ismoderated) Values ('" + txtManufactureName.Text + "','" + txtDescription.Text + "','true') WHERE ManufacturerName = " + currentManufacturer + ";";
}
else
{
query = "UPDATE VehicleManufacturer (ManufacturerName, ManufacturerDescription, Ismoderated) Values ('" + txtManufactureName.Text + "','" + txtDescription.Text + "','false') WHERE ManufacturerName = " + currentManufacturer + ";";
}
using (SqlCommand command = new SqlCommand(query, conn))
{
command.ExecuteNonQuery();
}
//using (SqlDataAdapter updater = new SqlDataAdapter(command))
// {
// DataTable dtable = new DataTable();
// updater.Fill(dtable);
// }
txtMessage.Text = "Manufacturer record changed Successfully";
txtManufactureName.Text = "";
txtDescription.Text = "";
checkBoxModerated.Checked = false;
}
else
{ // Record is a duplicate of existing database records. Give error message.
txtMessage.Text = "Sorry, that manufacturer name already exists.";
}
}

You are using the incorrect syntax for UPDATE statements.
Instead of
UPDATE Table (Fields) VALUES (Values) WHERE ...
It should be
UPDATE Table SET Field1=Value1, Field2=Value2 WHERE ...
Additionally, you have a SQL injection vulnerability (although this is not the reason for your exception).
Do not use string concatenation for SQL queries with user input. Use prepared statements instead.

Try this approach , it's safer also:
var isModerated = checkBoxModerated.Checked ; //true or false
//var isModerated = (checkBoxModerated.Checked)? 'true' : 'false' ;
command.Text = "UPDATE VehicleManufacturer
SET ManufacturerName = #manufacturerName,
ManufacturerDescription = #manufacturerDescription,
IsModerated = #isModerated
WHERE ManufacturerName = #manufacturer_name";
command.Parameters.AddWithValue("#manufacturerName", txtManufactureName.Text);
command.Parameters.AddWithValue("#manufacturerDescription", txtDescription.Text);
command.Parameters.AddWithValue("#isModerated", isModerated);
command.Parameters.AddWithValue("#manufacturer_name", txtManufactureName.Text);
command.ExecuteNonQuery();

Related

Invalid attempt to call read when reader is closed when inserting data

i have a button that when clicked inserts data from textbox and combobox fields into database tables, but every time i insert it gives me "Invalid attempt to call read when reader is closed". How can i get rid of this error. And tips on optimising the code are welcome, because i know im a total noob. thanks
private void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query1 = "insert into location(Storage, Shelf, columns, rows) values(" + txtWarehouse.Text + ", " + txtShelf.Text + ", " + txtColumn.Text + ", " + txtRow.Text + ")";
SqlCommand sqlCmd = new SqlCommand(Query1, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
sqlCon.Close();
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query3 = "SELECT LOCATION_ID FROM LOCATION WHERE storage='" + txtWarehouse.Text + "' AND shelf='" + txtShelf.Text + "' AND columns='"
+ txtColumn.Text + "' AND rows='" + txtRow.Text + "'";
SqlCommand sqlCmd1 = new SqlCommand(Query3, sqlCon);
SqlDataReader dr = sqlCmd1.ExecuteReader(); ;
while (dr.Read())
{
string LocationId = dr[0].ToString();
dr.Close();
string Query2 = "insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID) values ('" + txtSku.Text + "','" + txtNimetus.Text + "', '"
+ txtMin.Text + "', '" + txtMax.Text + "', '" + txtQuan.Text + "', '" + LocationId + "', '" + (cbCat.SelectedIndex+1) + "', '" + (cbMail.SelectedIndex+1) + "')";
SqlCommand sqlCmd = new SqlCommand(Query2, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
}
sqlCon.Close();
}
catch (Exception ed)
{
MessageBox.Show(ed.Message);
}
}
Let's try to make some adjustments to your code.
First thing to consider is to use a parameterized query and not a
string concatenation when you build an sql command. This is mandatory
to avoid parsing errors and Sql Injections
Second, you should encapsulate the disposable objects in a using statement
to be sure they receive the proper disposal when you have finished to
use them.
Third, you can get the LOCATION_ID from your table without running a
separate query simply adding SELECT SCOPE_IDENTITY() as second batch to your first command. (This works only if you have declared the LOCATION_ID field in the first table as an IDENTITY column)
Fourth, you put everything in a transaction to avoid problems in case
some of the code fails unexpectedly
So:
SqlTransaction tr = null;
try
{
string cmdText = #"insert into location(Storage, Shelf, columns, rows)
values(#storage,#shelf,#columns,#rows);
select scope_identity()";
using(SqlConnection sqlCon = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(cmdText, sqlCon))
{
sqlCon.Open();
using( tr = sqlCon.BeginTransaction())
{
// Prepare all the parameters required by the command
cmd.Parameters.Add("#storage", SqlDbType.Int).Value = Convert.ToInt32(txtWarehouse.Text);
cmd.Parameters.Add("#shelf", SqlDbType.Int).Value = Convert.ToInt32(txtShelf.Text);
cmd.Parameters.Add("#columns", SqlDbType.Int).Value = Convert.ToInt32(txtColumn.Text );
cmd.Parameters.Add("#rows", SqlDbType.Int).Value = Convert.ToInt32(txtRow.Text);
// Execute the command and get back the result of SCOPE_IDENTITY
int newLocation = Convert.ToInt32(cmd.ExecuteScalar());
// Set the second command text
cmdText = #"insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID)
values (#sku, #nimetus,#min,#max,#qty,#locid,#catid,#ordid)";
// Build a new command with the second text
using(SqlCommand cmd1 = new SqlCommand(cmdText, sqlCon))
{
// Inform the new command we are inside a transaction
cmd1.Transaction = tr;
// Add all the required parameters for the second command
cmd1.Parameters.Add("#sku", SqlDbType.NVarChar).Value = txtSku.Text;
cmd1.Parameters.Add("#nimetus",SqlDbType.NVarChar).Value = txtNimetus.Text;
cmd1.Parameters.Add("#locid", SqlDbType.Int).Value = newLocation;
.... and so on for the other parameters required
cmd1.ExecuteNonQuery();
// If we reach this point the everything is allright and
// we can commit the two inserts together
tr.Commit();
}
}
}
}
catch (Exception er)
{
// In case of exceptions do not insert anything...
if(tr != null)
tr.Rollback();
MessageBox.Show(er.Message);
}
Notice that in the first command I use parameters of type SqlDbType.Int because you haven't used single quotes around your text. This should be verified against the real data type of your table columns and adjusted to match the type. This is true as well for the second command where you put everything as text albeit some of those fields seems to be integer (_location_id_ is probably an integer). Please verify against your table.

Updating records in SQL Server database using ASP.NET

I am new to ASP.NET, I am facing some difficulty in updating records inside database in ASP.NET. My code is showing no errors, but still the records are not being updated. I am using SQL Server 2012.
Code behind is as follows:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["user"] != null)
{
con.Open();
string query = "Select * from Customers where UserName ='" + Session["user"] + "'";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
txt_name.Text = reader["CustName"].ToString();
txt_phonenumber.Text = reader["Contact"].ToString();
txt_address.Text = reader["CustAddress"].ToString();
txt_cardnum.Text = reader["CustAccountNo"].ToString();
txt_city.Text = reader["CustCity"].ToString();
txt_emailaddress.Text = reader["Email"].ToString();
txt_postalcode.Text = reader["CustPOBox"].ToString();
Cnic.Text = reader["CustCNIC"].ToString();
}
con.Close();
}
else
{
Response.Redirect("Login.aspx");
}
}
protected void BtnSubmit_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd2 = con.CreateCommand();
SqlCommand cmd1 = con.CreateCommand();
cmd1.CommandType = CommandType.Text;
cmd1.CommandText = "Select CustID from Customers where UserName = '" + Session["user"] + "'";
int id = Convert.ToInt32(cmd1.ExecuteScalar());
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "update Customers set CustName='" + txt_name.Text + "',CustCNIC='" + Cnic.Text + "',Email='" + txt_emailaddress.Text + "',CustAccountNo='" + txt_cardnum.Text + "',CustAddress='" + txt_address.Text + "',CustPOBox='" + txt_postalcode.Text + "' where CustID='" + id + "'";
cmd2.ExecuteNonQuery();
con.Close();
}
Help will be much appreciated. THANKS!
After debugging the result i am getting is this
cmd2.CommandText "update Customers set CustName='Umer Farooq',CustCNIC='42101555555555',Email='adada#gmail.com',CustAccountNo='0',CustAddress='',CustPOBox='0' where CustID='6'" string
Here Account Number And POBOX is 0 and address is going as empty string. But i have filled the text fields
First thing to do to fix this is to use good ADO techniques, using SqlParameters for the passed in values; and not the risky SQL Injection method of concatenating strings together.
This first portion does just that. I have added in the int sqlRA variable to read the results of the non-query, which will return Rows Affected by the query. This is wrapped in a simple try...catch routine to set the value to negative 1 on any error. Other error handling is up to you. That makes your code look something like this:
cmd1.Parameters.AddWithValue("#SessionUser", Session["User"]);
int id = Convert.ToInt32(cmd1.ExecuteScalar());
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "UPDATE Customers SET CustName = #CustName, CustCNIC = #CustCNIC, Email = #Email, CustAccountNo = #CustAccountNo, CustAddress = #CustAddress, CustPOBox = #CustPOBox WHERE (CustID = #CustID)";
cmd2.Parameters.AddWithValue("#CustName", txt_name.Text);
cmd2.Parameters.AddWithValue("#CustCNIC", Cnic.Text);
cmd2.Parameters.AddWithValue("#Email", txt_emailaddress.Text);
cmd2.Parameters.AddWithValue("#CustAccountNo", txt_cardnum.Text);
cmd2.Parameters.AddWithValue("#CustAddress", txt_address.Text);
cmd2.Parameters.AddWithValue("#CustPOBox", txt_postalcode.Text);
cmd2.Parameters.AddWithValue("#CustID", id);
int sqlRA
try { sqlRA = cmd2.ExecuteNonQuery(); }
catch (Exception ex) {
sqlRA = -1;
// your error handling
}
/* sqlRA values explained
-1 : Error occurred
0 : Record not found
1 : 1 Record updated
>1 :Multiple records updated
*/
Now reading through your code, all we are doing with the first query is mapping the Session["User"] to id, and then using that id in the second query to do the update, and that Username is not updated in the second. Waste of a query most likely, as we could use the Session["User"] to do the update. That will bring you down to this query, and still bring back that Rows Affected value back:
cmd0.CommandType = CommandType.Text;
cmd0.CommandText = "UPDATE Customers SET CustName = #CustName, CustCNIC = #CustCNIC, Email = #Email, CustAccountNo = #CustAccountNo, CustAddress = #CustAddress, CustPOBox = #CustPOBox WHERE (UserName = #SessionUser)";
cmd0.Parameters.AddWithValue("#CustName", txt_name.Text);
cmd0.Parameters.AddWithValue("#CustCNIC", Cnic.Text);
cmd0.Parameters.AddWithValue("#Email", txt_emailaddress.Text);
cmd0.Parameters.AddWithValue("#CustAccountNo", txt_cardnum.Text);
cmd0.Parameters.AddWithValue("#CustAddress", txt_address.Text);
cmd0.Parameters.AddWithValue("#CustPOBox", txt_postalcode.Text);
cmd0.Parameters.AddWithValue("#SessionUser", Session["User"]);
int sqlRA
try { sqlRA = cmd0.ExecuteNonQuery(); }
catch (Exception ex) {
sqlRA = -1;
// your error handling
}
/* sqlRA values explained
-1 : Error occurred
0 : Record not found
1 : 1 Record updated
>1 :Multiple records updated
*/
When BtnSubmit fires the event, the code in the Page_Load runs before the codes in BtnSubmit, replacing the values placed in the TextBox with the values from the Database before the Update takes place.

Error in gridviewUpdating asp.net with a timestamp update

I have two buttons, SetIn and SetOut. They both have the commandName UPDATE ( I have two buttons as I'd like the text to be different on the button depending on the value of one field in the row.
I'm getting a problem in that when I run the update SQL statement, it throws an error at me. It says:
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Incorrect syntax near '14'.
This means that there is an issue with the date and time stamp that I am trying to update the row with (I'm making the update at 14.02pm).
My aspx.cs page code is:
protected void GridView1_RowUpdating(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e)
{
Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
int rowToUpdate = Int32.Parse(id.Text);
con = new SqlConnection(cs);
int scopeValue;
con = new SqlConnection(cs);
cmd = new SqlCommand();
cmd.CommandText = "SELECT in_scope FROM " + databaseName + " WHERE id = '" + rowToUpdate + "'";
cmd.Parameters.AddWithValue("#id", rowToUpdate);
cmd.Connection = con;
try
{
con.Open();
scopeValue = Convert.ToInt32(cmd.ExecuteScalar());
//database_entries.Text = recordCount.ToString();
}
finally
{
con.Close();
}
string modifiedBy = userManagement.getWeldID();
string updateDate = DateTime.UtcNow.ToString("dd/MMM/yyyy HH:mm:ss");
{
if (scopeValue == 1)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '0', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
if (scopeValue == 0)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '1', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
}
}
I'm basically trying to get the scopeValue (0 or 1) of the row, and if the Update command is called, and the scopeValue was previously 0, set it to 1 now and vice versa. I also need to update the time that the change was made and who made the change in that row. (these are both displayed in the gridview)
Any help would be much appreciated as I am a beginner to ASP.NET and C# and SQL SERVER!!
You are sending a DateTime as a string (without even enclosing single quotes date_updated = '" + updateDate + "') and that will always cause problems.
It's better to use parameters in your query. This prevents SQL injection, improves readability, ensures type safety, no more worries about the correct use of quotation marks etc.
string sqlStatement = "UPDATE dbo.Fair_Use_InScope_MIF_Alex_temp SET in_scope = 0, modified_by = #modifiedBy, date_updated = #updateDate WHERE (id = #rowToUpdate)";
using (SqlConnection connection = new SqlConnection(cs))
using (SqlCommand command = new SqlCommand(sqlStatement, connection))
{
command.Parameters.Add("#modifiedBy", SqlDbType.VarChar).Value = modifiedBy;
command.Parameters.Add("#updateDate", SqlDbType.DateTime).Value = DateTime.Now;
command.Parameters.Add("#rowToUpdate", SqlDbType.Int).Value = 35;
connection.Open();
command.ExecuteNonQuery();
}

How do I check Duplicate [duplicate]

This question already has an answer here:
how to i search if there is a same id in a database?
(1 answer)
Closed 6 years ago.
private void Add_Box_Click(object sender, EventArgs e)
{
string phoneNumber;
if (string.IsNullOrWhiteSpace(Id_Box.Text))// To check if the Id_box is empty or not
{
MessageBox.Show("Please Enter Your ID");// need to enter ID in order to save data
}
///////////////////////////////////////////check the Extension Box////////////////////////////////////////////////////////////////////////////////////
else
{
if (string.IsNullOrWhiteSpace(Ext_Box.Text))
{
phoneNumber = Phone_Box.Text;// if it is empty then it will only show the phone number
}
else
{
phoneNumber = Phone_Box.Text + "," + Ext_Box.Text; // show the phone number and the extension if there is something in the extension
}
///////////////////////////////////////////////////////////Save it to the Database///////////////////////////////////////////////////////
SqlCeCommand cmd = new SqlCeCommand("INSERT INTO Contact_List(Id, Name, Adress1, Adress2, City, Province, Postal_Code, Phone, Email)VALUES('" + Id_Box.Text + "','" + Name_Box.Text + "','" + Adress1_Box.Text + "','" + Adress2_Box.Text + "','" + City_Box.Text + "','" + Province_Box.Text + "','" + Code_Box.Text + "','" + phoneNumber + "','" + Email_Box.Text + "')", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Information Added", "Confirm");
/////////////////////////////////////Show new set of data after insert a new data/////////////////////////////////////////////////////////////
SqlCeCommand cmd2 = new SqlCeCommand("Select * from Contact_List;", con);
try
{
SqlCeDataAdapter sda = new SqlCeDataAdapter();
sda.SelectCommand = cmd2;
DataTable dt = new DataTable();
sda.Fill(dt);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dataGridView1.DataSource = bs;
sda.Update(dt);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
////////////////////////////////Empty The Box/////////////////////////////////////////////////////////////////////////////////////////////////
Id_Box.Text = String.Empty;
Name_Box.Text = String.Empty;
Adress1_Box.Text = String.Empty;
Adress2_Box.Text = String.Empty;
City_Box.Text = String.Empty;
Province_Box.Text = String.Empty;
Code_Box.Text = String.Empty;
Phone_Box.Text = String.Empty;
Ext_Box.Text = String.Empty;
Email_Box.Text = String.Empty;
}
}
This code will store Id, name, etc to the database. But when there is a same Id, i want to delete it. When i delete it both of the same Id will be deleted and i don't want that so is there anyway to check duplicate before it store it to the database?
I want to do something like this if possible :
if ( the values in id column == to the Id_textBox) {
MessageBox.Show("Duplicate ,PLease enter anotherId")
}
Possible?
Before executing your INSERT SQL statement, try running the SQL int ContactCount = (int)cmd.ExecuteScalar("SELECT COUNT(*) FROM CONTACT_LIST WHERE Id = '" + Id_Box.Text + "'")
If ContactCount > 0 then you can do the DELETE your suggesting.
Can I also recommend that you use a SQL UPDATE instead of DELETEing and INSERTing the same record.
Also, read-up on SQL Injection attacks. Building a SQL statement, like you're doing here, using the values input by a user leaves you exposed to that type of vulnerability.
First of all, like in all these answers: Don't use string concatenation but parametrized queries to prevent SQL-injection.
For your problem:
You can either do a
string query = "SELECT count(*) from ContactList Where id = #id";
SqlCeCommand cmd = new SqlCeCommand(query, connection);
cmd.Parameters.Add("#id", SqlDbType.NVarChar, 50).Value = Id_Box.Text;
int count = (int)cmd.ExecuteScalar();
if count > 0 the id already exists.
Or you can do a
string query "IF NOT EXISTS(SELECT count(*) from ContactList Where id = #id) INSERT INTO ContactList(Id, ...) VALUES(#id, ...)";
SqlCeCommand cmd = new SqlCeCommand(query, connection);
cmd.Parameters.Add("#id", SqlDbType.NVarChar, 50).Value = Id_Box.Text;
int count = cmd.ExecuteNonQuery();
count will then contain the number of rows affected, ie 0 if the value already existed, or 1 if it did not exist, but was newly inserted.

How to insert a data table into SQL Server database table?

I have imported data from some Excel file and I have saved it into a datatable. Now I'd like to save this information in my SQL Server database.
I saw a lot of information on the web but I cannot understand it:
Someone said insert line by line another suggested bulk update... etc: what it better?
Should I use OLE or SQL Server objects (like dataAdapter or connection)?
My need is to read the employee weekly hours report, from his Excel file and save it to a database table where all the reports are saved (updating the db with new records every week).
The Excel file contains reports only for the current week.
Create a User-Defined TableType in your database:
CREATE TYPE [dbo].[MyTableType] AS TABLE(
[Id] int NOT NULL,
[Name] [nvarchar](128) NULL
)
and define a parameter in your Stored Procedure:
CREATE PROCEDURE [dbo].[InsertTable]
#myTableType MyTableType readonly
AS
BEGIN
insert into [dbo].Records select * from #myTableType
END
and send your DataTable directly to sql server:
using (var command = new SqlCommand("InsertTable") {CommandType = CommandType.StoredProcedure})
{
var dt = new DataTable(); //create your own data table
command.Parameters.Add(new SqlParameter("#myTableType", dt));
SqlHelper.Exec(command);
}
To edit the values inside stored-procedure, you can declare a local variable with the same type and insert input table into it:
DECLARE #modifiableTableType MyTableType
INSERT INTO #modifiableTableType SELECT * FROM #myTableType
Then, you can edit #modifiableTableType:
UPDATE #modifiableTableType SET [Name] = 'new value'
If it's the first time for you to save your datatable
Do this (using bulk copy). Assure there are no PK/FK constraint
SqlBulkCopy bulkcopy = new SqlBulkCopy(myConnection);
//I assume you have created the table previously
//Someone else here already showed how
bulkcopy.DestinationTableName = table.TableName;
try
{
bulkcopy.WriteToServer(table);
}
catch(Exception e)
{
messagebox.show(e.message);
}
Now since you already have a basic record. And you just want to check new record with the existing one. You can simply do this.
This will basically take existing table from database
DataTable Table = new DataTable();
SqlConnection Connection = new SqlConnection("ConnectionString");
//I assume you know better what is your connection string
SqlDataAdapter adapter = new SqlDataAdapter("Select * from " + TableName, Connection);
adapter.Fill(Table);
Then pass this table to this function
public DataTable CompareDataTables(DataTable first, DataTable second)
{
first.TableName = "FirstTable";
second.TableName = "SecondTable";
DataTable table = new DataTable("Difference");
try
{
using (DataSet ds = new DataSet())
{
ds.Tables.AddRange(new DataTable[] { first.Copy(), second.Copy() });
DataColumn[] firstcolumns = new DataColumn[ds.Tables[0].Columns.Count];
for (int i = 0; i < firstcolumns.Length; i++)
{
firstcolumns[i] = ds.Tables[0].Columns[i];
}
DataColumn[] secondcolumns = new DataColumn[ds.Table[1].Columns.Count];
for (int i = 0; i < secondcolumns.Length; i++)
{
secondcolumns[i] = ds.Tables[1].Columns[i];
}
DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false);
ds.Relations.Add(r);
for (int i = 0; i < first.Columns.Count; i++)
{
table.Columns.Add(first.Columns[i].ColumnName, first.Columns[i].DataType);
}
table.BeginLoadData();
foreach (DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r);
if (childrows == null || childrows.Length == 0)
table.LoadDataRow(parentrow.ItemArray, true);
}
table.EndLoadData();
}
}
catch (Exception ex)
{
throw ex;
}
return table;
}
This will return a new DataTable with the changed rows updated. Please ensure you call the function correctly. The DataTable first is supposed to be the latest.
Then repeat the bulkcopy function all over again with this fresh datatable.
I am giving a very simple code, which i used in my solution (I have the same problem statement as yours)
SqlConnection con = connection string ;
//new SqlConnection("Data Source=.;uid=sa;pwd=sa123;database=Example1");
con.Open();
string sql = "Create Table abcd (";
foreach (DataColumn column in dt.Columns)
{
sql += "[" + column.ColumnName + "] " + "nvarchar(50)" + ",";
}
sql = sql.TrimEnd(new char[] { ',' }) + ")";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
cmd.ExecuteNonQuery();
using (var adapter = new SqlDataAdapter("SELECT * FROM abcd", con))
using(var builder = new SqlCommandBuilder(adapter))
{
adapter.InsertCommand = builder.GetInsertCommand();
adapter.Update(dt);
// adapter.Update(ds.Tables[0]); (Incase u have a data-set)
}
con.Close();
I have given a predefined table-name as "abcd" (you must take care that a table by this name doesn't exist in your database).
Please vote my answer if it works for you!!!! :)
I would suggest you go for bulk insert as suggested in this article :
Bulk Insertion of Data Using C# DataTable and SQL server OpenXML function
public bool BulkCopy(ExcelToSqlBo objExcelToSqlBo, DataTable dt, SqlConnection conn, SqlTransaction tx)
{
int check = 0;
bool result = false;
string getInsert = "";
try
{
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
if (dr != null)
{
if (check == 0)
{
getInsert = "INSERT INTO [tblTemp]([firstName],[lastName],[Father],[Mother],[Category]" +
",[sub_1],[sub_LG2])"+
" select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString();
check += 1;
}
else
{
getInsert += " UNION ALL ";
getInsert += " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString() ;
check++;
}
}
}
result = common.ExecuteNonQuery(getInsert, DatabasesName, conn, tx);
}
else
{
throw new Exception("No row for insertion");
}
dt.Dispose();
}
catch (Exception ex)
{
dt.Dispose();
throw new Exception("Please attach file in Proper format.");
}
return result;
}
//best way to deal with this is sqlbulkcopy
//but if you dont like it you can do it like this
//read current sql table in an adapter
//add rows of datatable , I have mentioned a simple way of it
//and finally updating changes
Dim cnn As New SqlConnection("connection string")
cnn.Open()
Dim cmd As New SqlCommand("select * from sql_server_table", cnn)
Dim da As New SqlDataAdapter(cmd)
Dim ds As New DataSet()
da.Fill(ds, "sql_server_table")
Dim cb As New SqlCommandBuilder(da)
//for each datatable row
ds.Tables("sql_server_table").Rows.Add(COl1, COl2)
da.Update(ds, "sql_server_table")
I found that it was better to add to the table row by row if your table has a primary key. Inserting the entire table at once creates a conflict on the auto increment.
Here's my stored Proc
CREATE PROCEDURE dbo.usp_InsertRowsIntoTable
#Year int,
#TeamName nvarchar(50),
AS
INSERT INTO [dbo.TeamOverview]
(Year,TeamName)
VALUES (#Year, #TeamName);
RETURN
I put this code in a loop for every row that I need to add to my table:
insertRowbyRowIntoTable(Convert.ToInt16(ddlChooseYear.SelectedValue), name);
And here is my Data Access Layer code:
public void insertRowbyRowIntoTable(int ddlValue, string name)
{
SqlConnection cnTemp = null;
string spName = null;
SqlCommand sqlCmdInsert = null;
try
{
cnTemp = helper.GetConnection();
using (SqlConnection connection = cnTemp)
{
if (cnTemp.State != ConnectionState.Open)
cnTemp.Open();
using (sqlCmdInsert = new SqlCommand(spName, cnTemp))
{
spName = "dbo.usp_InsertRowsIntoOverview";
sqlCmdInsert = new SqlCommand(spName, cnTemp);
sqlCmdInsert.CommandType = CommandType.StoredProcedure;
sqlCmdInsert.Parameters.AddWithValue("#Year", ddlValue);
sqlCmdInsert.Parameters.AddWithValue("#TeamName", name);
sqlCmdInsert.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (sqlCmdInsert != null)
sqlCmdInsert.Dispose();
if (cnTemp.State == ConnectionState.Open)
cnTemp.Close();
}
}
From my understanding of the question,this can use a fairly straight forward solution.Anyway below is the method i propose ,this method takes in a data table and then using SQL statements to insert into a table in the database.Please mind that my solution is using MySQLConnection and MySqlCommand replace it with SqlConnection and SqlCommand.
public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat)
{
for (int i = 0; i < tblFormat.Rows.Count; i++)
{
String InsertQuery = string.Empty;
InsertQuery = "INSERT INTO customercredit " +
"(ACCOUNT_CODE,NAME,CURRENCY,CREDIT_LIMIT) " +
"VALUES ('" + tblFormat.Rows[i]["AccountCode"].ToString() + "','" + tblFormat.Rows[i]["Name"].ToString() + "','" + tblFormat.Rows[i]["Currency"].ToString() + "','" + tblFormat.Rows[i]["CreditLimit"].ToString() + "')";
using (MySqlConnection destinationConnection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
using (var dbcm = new MySqlCommand(InsertQuery, destinationConnection))
{
destinationConnection.Open();
dbcm.ExecuteNonQuery();
}
}
}//CreditLimit

Categories