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
Related
I got 10 tables in SQL server and I want to export those table values to a ms access database which also contains 10 tables. so is there any way to export data using c# code.
I don't want to write lots of code for each table to get data from a particular table then insert row by row to the respective access table is there any shortcut available that I can use please do let me know.
i thik this code help you.
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\"Database.accdb\";Persist Security Info=False;");
//command to insert each ASIN
OleDbCommand cmd = new OleDbCommand();
//command to update each column (ASIN, Retail... from CSV)
OleDbCommand cmd1 = new OleDbCommand();
//load csv data to dtCSV datatabe
DataTable dtCSV = new DataTable();
dtCSV = ds.Tables[0];
// Now we will collect data from data table and insert it into database one by one
// Initially there will be no data in database so we will insert data in first two columns
// and after that we will update data in same row for remaining columns
// The logic is simple. 'i' represents rows while 'j' represents columns
cmd.Connection = myConnection;
cmd.CommandType = CommandType.Text;
cmd1.Connection = myConnection;
cmd1.CommandType = CommandType.Text;
myConnection.Open();
for (int i = 0; i <= dtCSV.Rows.Count - 1; i++)
{
cmd.CommandText = "INSERT INTO " + lblTable.Text + "(ID, " + dtCSV.Columns[0].ColumnName.Trim() + ") VALUES (" + (i + 1) + ",'" + dtCSV.Rows[i].ItemArray.GetValue(0) + "')";
cmd.ExecuteNonQuery();
for (int j = 1; j <= dtCSV.Columns.Count - 1; j++)
{
cmd1.CommandText = "UPDATE " + lblTable.Text + " SET [" + dtCSV.Columns[j].ColumnName.Trim() + "] = '" + dtCSV.Rows[i].ItemArray.GetValue(j) + "' WHERE ID = " + (i + 1);
cmd1.ExecuteNonQuery();
}
}
myConnection.Close();
If this is a one-off operation, you should use Data Export features of SQL Server or import features of Access to perform this. They'll be simple enough for end-users who don't want to write code. Therein you simply select the database, the tables that you want to export and the destination database and everything will get exported on click of a button.
First make sure that the access table columns have the same column names and similar types. Then you can use this function which I believe is very fast and elegant.
public void AccessBulkCopy(DataTable table)
{
foreach (DataRow r in table.Rows)
r.SetAdded();
var myAdapter = new OleDbDataAdapter("SELECT * FROM " + table.TableName, _myAccessConn);
var cbr = new OleDbCommandBuilder(myAdapter);
cbr.QuotePrefix = "[";
cbr.QuoteSuffix = "]";
cbr.GetInsertCommand(true);
myAdapter.Update(table);
}
use this code
Well i got the answer. i used for loop to generate query string like below.
public void MainAccess(int _i)
{
DataTable dt = ds.Tables[_i];
string sql = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
sql = sql + "INSERT INTO "+ _tableString[_i] + " values('";
for (int j = 0; j < dt.Columns.Count; j++)
{
sql += dt.Rows[i][j].ToString().Trim();
if (j != dt.Columns.Count - 1)
{
sql += "','";
}
else
{
sql += "')";
}
}
ExecuteQuery(sql);
sql = null;
}
}
I've got a c#.Net 4.5 console application and I'm trying to insert data from a DataTable to a SQL Server 2008R2 database table. I get no errors, but no data gets inserted. Here's my code:
Int32 newID = 0;
DataTable dtMaxUserID = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect("SELECT MAX(UserID)+1 AS NewID FROM TIUser", false, "TrackitCN");
newID = Convert.ToInt32(dtMaxUserID.Rows[0]["NewID"].ToString());
//Get new users from AllUserData
DataColumn dcRowID = new DataColumn("RowID", typeof(Int32));
//dcRowID.AllowDBNull = false;
dcRowID.AutoIncrement = true;
dcRowID.AutoIncrementSeed = 1;
dcRowID.AutoIncrementStep = 1;
//dcRowID.Unique = true;
//dcRowID.ColumnName = "RowID";
DataTable dtNewUsers = new DataTable();
dtNewUsers.Columns.Add(dcRowID);
dtNewUsers.Columns.Add("MaxID");
dtNewUsers.Columns.Add("UserID");
dtNewUsers.Columns.Add("FullName");
dtNewUsers.Columns.Add("Title");
dtNewUsers.Columns.Add("Phone");
dtNewUsers.Columns.Add("EMailAddr");
dtNewUsers.Columns.Add("Fax");
dtNewUsers.Columns.Add("Dept");
dtNewUsers.Columns.Add("Dept_Num");
dtNewUsers.Columns.Add("Location");
dtNewUsers.Columns.Add("UserDef_1");
dtNewUsers.Columns.Add("UserDef_2");
dtNewUsers.Columns.Add("Login");
dtNewUsers.Columns.Add("Password");
dtNewUsers.Columns.Add("PasswordFlags");
dtNewUsers.Columns.Add("LanguageID");
dtNewUsers.Columns.Add("NTAuthentication");
dtNewUsers.Columns.Add("NTAccount");
dtNewUsers.Columns.Add("SID");
dtNewUsers.Columns.Add("SelfServiceAccess");
dtNewUsers.Columns.Add("ImagePath");
dtNewUsers.Columns.Add("CompFlag");
dtNewUsers.Columns.Add("Employee_ID");
dtNewUsers.Columns.Add("SessionID");
string strQuery = "SELECT " + newID + " AS MaxID, LName" + ", " + "FName AS FullName, Title, Phone, EMail AS EmailAddr, Fax, Department AS Dept, Office AS Location, [Login] AS Employee_ID FROM [User] WHERE StartDate >= CAST(DATEPART(year,getdate()) AS varchar) + '-' + CAST(DATEPART(month,getdate()) AS varchar) + '-' + CAST(DATEPART(day,getdate())-1 AS varchar)";
DataTable dtTemp = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect(strQuery, false, "AllUserDataCN");
foreach (DataRow row in dtTemp.Rows)
dtNewUsers.ImportRow(row);
SqlTransaction tran = null;
try
{
connection.Open();
tran = connection.BeginTransaction();
//Insert new users into TIUser
SqlDataAdapter TIUser_adapter = new SqlDataAdapter();
string queryString = "SELECT * FROM TIUser WHERE 1 = 0";
TIUser_adapter.SelectCommand = new SqlCommand(queryString, connection, tran);
TIUser_adapter.Fill(dtNewUsers);
dtNewUsers.AcceptChanges();
TIUser_adapter.Update(dtNewUsers);
tran.Commit();
}
catch (System.Exception ex)
{
tran.Rollback();
throw ex;
}
finally
{
connection.Close();
}
GeneralClassLibrary is a class library we use here for a number of things; here it just executes a SELECT statement on a database. TIUser is the database table. The DataTable, dtNewUsers contains one row. I've verified that by debugging the code and inspecting the DataTable after the ImportRow is done.
After following the reply from user3787557 (THANK YOU!), I'm closer, but I'm getting a concurrency violation. I'm working on a development database, and all I'm doing is inserting a record, so I have no idea why there'd be a concurrency violation. One possibility: I alter the structure of the DataTable dtNewUsers by adding two columns. However, before I do the update, I remove those columns. The InsertCommand is fine; I've checked it in SSMS and it parses. Here's my new code:
using (SqlConnection connection = new SqlConnection(GeneralClassLibrary.GeneralConfigurationManager.ConnectionStrings["TrackitCN"].ConnectionString))
{
SqlTransaction tran = null;
connection.Open();
tran = connection.BeginTransaction();
try
{
//Create empty TIUser Data Adapter
SqlDataAdapter TIUser_adapter = new SqlDataAdapter();
SqlCommandBuilder TIUser_builder = new SqlCommandBuilder(TIUser_adapter);
string queryString = "SELECT * FROM TIUser WHERE 1 = 0";
TIUser_adapter.SelectCommand = new SqlCommand(queryString, connection, tran);
TIUser_adapter.InsertCommand = TIUser_builder.GetInsertCommand();
TIUser_adapter.UpdateCommand = TIUser_builder.GetUpdateCommand();
//Get new users from AllUserData
DataTable dtNewUsers = new DataTable();
TIUser_adapter.Fill(dtNewUsers);
DataColumn dcRowID = new DataColumn("RowID", typeof(Int32));
dcRowID.AutoIncrement = true;
dcRowID.AutoIncrementSeed = 1;
dcRowID.AutoIncrementStep = 1;
dtNewUsers.Columns.Add(dcRowID);
dtNewUsers.Columns.Add("MaxID"); string strQuery = "SELECT " + newID + " AS MaxID, LName + ', ' + FName AS FullName, Title, Phone, EMail AS EmailAddr, Fax, Department AS Dept, Office AS Location, [Login] AS Employee_ID FROM [User] WHERE StartDate >= CAST(DATEPART(year,getdate()) AS varchar) + '-' + CAST(DATEPART(month,getdate()) AS varchar) + '-' + CAST(DATEPART(day,getdate())-1 AS varchar)";
DataTable dtTemp = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect(strQuery, false, "AllUserDataCN");
foreach (DataRow row in dtTemp.Rows)
dtNewUsers.ImportRow(row);
//Make sure new users aren't already in Trackit
foreach (DataRow row in dtNewUsers.Rows)
{
row["UserID"] = (Convert.ToInt32(row["RowID"]) + Convert.ToInt32(row["MaxID"])).ToString();
DataTable dtOverlap = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect("SELECT * FROM TIUser WHERE Employee_ID = '" + row["Employee_ID"].ToString() + "'", false, "TrackitCN");
if (dtOverlap.Rows.Count > 0)
dtNewUsers.Rows.Remove(row);
}
//Remove MaxID and RowID Columns
dtNewUsers.Columns.Remove("MaxID");
dtNewUsers.Columns.Remove("RowID")
TIUser_adapter.Update(dtNewUsers);
tran.Commit();
}
catch (System.Exception ex)
{
GeneralClassLibrary.GeneralEmail.ExceptionNotification(System.Reflection.Assembly.GetExecutingAssembly().ToString(), ex.Message, ex.StackTrace);
tran.Rollback();
throw ex;
}
finally
{
connection.Close();
}
}
The Stack Trace I get is:
at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.Update(DataTable dataTable)
at UpdateTrackitUsers.Program.Main(String[] args) in c:\Users\06717\Documents\Visual Studio 2012\Projects\UpdateTrackitUsersConsole\UpdateTrackitUsersConsole\Program.cs:line 91
Line 87 is the line:
TIUser_adapter.Update(dtNewUsers);
This is the code that worked for me. Basically what you're missing on your code is to use SqlCommandBuilder to create InsertCommand and UpdateCommand. Also GET RID of AcceptChanges(). That is going to cause the new row to NOT be sent to the database. One last thing: make sure you mark the MDF database file (if you're using one) properties with "Do Not Copy" otherwise the database gets overridden every time you compile and you can't see your changes.
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.SelectCommand = new SqlCommand(queryString, connection);
adapter.InsertCommand = builder.GetInsertCommand();
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.DeleteCommand = builder.GetDeleteCommand();
DataTable dt = new DataTable();
adapter.Fill(dt);
DataRow row = dt.NewRow();
row["RegionID"] = 5;
row["RegionDescription"] = "Some region";
dt.Rows.Add(row);
//dt.AcceptChanges();
int counter = adapter.Update(dt);
}
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();
I'm trying to a simple insert list of rows from a DataGridView to a database.
I have made a checkedbox that upon checked, the item will be added to the DataGridView. Now i'm attempting to do the INSERT part. This what I have come up so far:
try
{
string strAppointment = "SELECT appointmentID FROM APPOINTMENT WHERE appointmentID=#searchappointmentID";
SqlCommand cmdAppointment = new SqlCommand(strAppointment, connection);
cmdAppointment.Parameters.AddWithValue("#searchappointmentID", txtAppointmentID.Text);
connection.Open();
for (int i = 0; i < dataPrescription.Rows.Count; i++)
{
string firstColumn = dataPrescription[0, dataPrescription.CurrentCell.RowIndex].Value.ToString();
string strMedications = "SELECT medicationID FROM MEDICATION WHERE medicationName= ('" + firstColumn + "')";
SqlCommand cmdMedications = new SqlCommand(strMedications, connection);
SqlDataReader readMedications = cmdMedications.ExecuteReader();
if (readMedications.Read())
{
string getDrugID = readMedications["medicationID"].ToString();
string strPrescriptions = "INSERT INTO PRESCRIPTION (appointmentID, medicationID, quantity) " +
"VALUES (#insertAppointment, "
+ getDrugID + ", "
+ dataPrescription.Rows[i].Cells["columnQuantity"].Value + ");";
SqlCommand cmdPrescriptions = new SqlCommand(strPrescriptions, connection);
cmdPrescriptions.Parameters.AddWithValue("#insertAppointment", txtAppointmentID.Text);
prescriptionsResult = cmdAppointment.ExecuteNonQuery();
}
readMedications.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
finally
{
connection.Close();
}
Right now it giving me this error: "There is already an open DataReader associated with the command which must be closed first". I don't know what I've done wrong
Try this: (initialize the datareader)
for (int i = 0; i < dataPrescription.Rows.Count; i++)
{
string firstColumn = dataPrescription[0, dataPrescription.CurrentCell.RowIndex].Value.ToString();
string strMedications = "SELECT medicationID FROM MEDICATION WHERE medicationName= ('" + firstColumn + "')";
SqlCommand cmdMedications = new SqlCommand(strMedications, connection);
SqlDataReader dr = new SqlDataReader(); //Insert this line in your code
SqlDataReader readMedications = cmdMedications.ExecuteReader();
It looks like you're trying to execute a command using a connection that's occupied with the reader, and I would look at that as being the problem. Instead of trying to execute the insert inside the reader, try reading the data to a collection and closing the reader, then iterating the connection to make you're updates.
I'm new to SQL integration with C# WinForms stuff. I have an existing database and simply want to take the values from the text boxes on my form and efficiently write all of them to one row in a SQL Server database.
So this is what I've got, I was trying to make something generic, but if this isn't a good practice, let me know.
Every time I call this, it creates a new row. I know this is because of the ...Rows.Add() line but since my database table has a whole bunch of columns and the form has a bunch of textboxes, I was hoping to not make a gigantic command string.
static public void addToExistingTable(string table, string column, string value, SqlDbType valueType)
{
try
{
using (SqlConnection con = new SqlConnection(Global.connectionString))
{
using (SqlDataAdapter dataAdapter = new SqlDataAdapter())
{
string selectString = "SELECT " + column + " from dbo." + table;
string insertString = "INSERT into dbo." + table + " (" + column + ") values (#" + column + ")";
dataAdapter.SelectCommand = new SqlCommand(selectString, con);
dataAdapter.InsertCommand = new SqlCommand(insertString, con);
dataAdapter.InsertCommand.Parameters.Add(new SqlParameter(column, valueType, value.Length, column));
using (DataSet dataSet = new DataSet())
{
dataAdapter.Fill(dataSet);
DataRow newRow = dataSet.Tables[0].NewRow();
newRow[column] = value;
dataSet.Tables[0].Rows.Add(newRow);
dataAdapter.Update(dataSet);
}
}
}
}
catch (SqlException exp)
{
Console.WriteLine("Insert Error: " + exp.Message);
}
}
Please let me know if there is a good practice or resource to add a new row to a SQL database from a collection of form controls (textboxes).