The current solution i implemented is awful!
I use a for... loop for inserting records from an ADO.NET data-table into an SQL table.
I would like to insert at once the data-table into the SQL table, without iterating...
Is that possible, or am i asking too much?
You can pass the entire DataTable as a single Table Valued Parameter and insert the entire TVP at once. The following is the example from Table-Valued Parameters in SQL Server 2008 (ADO.NET):
// Assumes connection is an open SqlConnection.
using (connection)
{
// Create a DataTable with the modified rows.
DataTable addedCategories = CategoriesDataTable.GetChanges(
DataRowState.Added);
// Define the INSERT-SELECT statement.
string sqlInsert =
"INSERT INTO dbo.Categories (CategoryID, CategoryName)"
+ " SELECT nc.CategoryID, nc.CategoryName"
+ " FROM #tvpNewCategories AS nc;"
// Configure the command and parameter.
SqlCommand insertCommand = new SqlCommand(
sqlInsert, connection);
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
"#tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.CategoryTableType";
// Execute the command.
insertCommand.ExecuteNonQuery();
}
TVP are only available in SQL 2008.
I think you are looking for SQLBulkCopy.
SqlBulkCopy is the simplest solution.
using (SqlConnection dbConn = new SqlConnection(connectionString))
{
dbConn.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(dbConn))
{
bulkCopy.DestinationTableName =
"dbo.MyTable";
try
{
bulkCopy.WriteToServer(myDataTable, DataRowState.Added);
}
catch (Exception ex)
{
myLogger.Error("Fail to upload session data. ", ex);
}
}
}
You can create SqlBulkCopyColumnMapping if the columns in your DataTable don't match your database table.
You can also try the following method.
private void button1_Click(object sender, EventArgs e)
{
tabevent();
DataSet ds = new DataSet();
DataTable table = new DataTable("DataFromDGV");
ds.Tables.Add(table);
foreach (DataGridViewColumn col in dataGridView1.Columns)
table.Columns.Add(col.HeaderText, typeof(string));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
table.Rows.Add(row);
foreach (DataGridViewCell cell in row.Cells)
{
table.Rows[row.Index][cell.ColumnIndex] = cell.Value;
}
}
// DataTable ds1changes = ds1.Tables[0].GetChanges();
if (table != null)
{
SqlConnection dbConn = new SqlConnection(#"Data Source=wsswe;Initial Catalog=vb;User ID=sa;Password=12345");
SqlCommand dbCommand = new SqlCommand();
dbCommand.Connection = dbConn;
foreach (DataRow row in table.Rows)
{
if (row["quantity"] != null && row["amount"]!=null && row["itemname"]!=null)
{
if (row["amount"].ToString() != string.Empty)
{
dbCommand.CommandText =
"INSERT INTO Bill" +
"(Itemname,Participants,rate,Quantity,Amount)" +
"SELECT '" + Convert.ToString(row["itemname"]) + "' AS Itemname,'" + Convert.ToString(row["Partcipants"]) + "' AS Participants,'" + Convert.ToInt32(row["rate"]) + "' AS rate,'" +
Convert.ToInt32(row["quantity"]) + "' AS Quantity,'" + Convert.ToInt32(row["amount"]) + "' AS Amount";
dbCommand.Connection.Open();
dbCommand.ExecuteNonQuery();
if (dbCommand.Connection.State != ConnectionState.Closed)
{
dbCommand.Connection.Close();
}
MessageBox.Show("inserted");
}
}
}
}
}
Related
So what I'm trying to do is once I click a button. I want one sql query to insert values to the "Return_Process" Table and another sql query to delete data from the matching loan ID in another table, which is "Loan_Process".
This is the code I have written but its not deleting anything, its inserting the values to the return process but not deleting it from the loan process.
//Global variable declaration
string path;
string sql;
string sql2;
//create a method for database connection
public void connection()
{
//connection string
path = #"Data Source=NATHAN-PC\SQLEXPRESS;Initial Catalog=ASP;Integrated Security=True";
}
protected void Button1_Click(object sender, EventArgs e)
{
{
connection();
SqlConnection con = new SqlConnection(path);
con.Open();
//try
{
sql = "INSERT INTO Return_Process (Return_ID, FIne, Actual_Returned_Date, Loan_ID) VALUES ('" + txtRID.Text + "','" + txtfine.Text + "','" + TextBox1.Text + "','" + txtLID.Text + "')";
sql2 = "Delete FROM Loan_Process WHERE Loan_ID='"+txtLID+"'";
SqlCommand cmd = new SqlCommand(sql, con);
cmd.ExecuteNonQuery();
//lblerrormsg.Visible = true;
//lblerrormsg.Text = "Success";
con.Close();
//GridView1.DataBind();
}
//catch (SqlException)
//{
// //lblerrormsg.Visible = true;
// //lblerrormsg.Text = "Invalid";
//}
con.Close();
//GridView1.DataBind();
}
}
}
}
I'm pretty bad at ASP.net, so if someone could tell me what to do to execute both queries at the same time, would greatly appreciate it.
Do something like this:
//your code
sql = "INSERT INTO Return_Process (Return_ID, FIne, Actual_Returned_Date, Loan_ID)"
+ " VALUES (#rid, #fine, #retDate, #lid); " //note ; inside
+ "Delete FROM Loan_Process WHERE Loan_ID=#lid;";
var cmd = new SqlCommand(sql, con);
cmd.Parameters.Add("#rid", SqlDbType.Int).Value = Int.Parse(txtRID.Text);
//similar for 3 remaining parameters. Just set correct SqlDbType
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Here is ehat I try to do
on button_click I read the values from the text boxes and insert them in them in the database.
as tourist number for example maybe two or three tourists with ExecuteScalar; i get the ids of teh tourists which are inserted!
public void cmdInsert_OnClick(object sender, EventArgs e)
{
if (Page.IsValid)
{
string numtourist = (string)Session["tourist_number"];
for (int i = 0; i < Int32.Parse(numtourist); i++)
{
TextBox tx888 = (TextBox)FindControl("txtNameK" + i.ToString());
TextBox tx888_1 = (TextBox)FindControl("txtMidNameK" + i.ToString());
TextBox tx888_2 = (TextBox)FindControl("txtLastNameK" + i.ToString());
string insertSQL = "INSERT INTO Tourist (Excursion_ID, Excursion_date_ID, Name_kir,Midname_kir, Lastname_kir)";
insertSQL += " VALUES (#Excursion_ID, #Excursion_date_ID, #Name_kir,#Midname_kir, #Lastname_kir) SELECT ##IDENTITY";
string connectionString = "Data Source = localhost\\SQLExpress;Initial Catalog=excursion;Integrated Security=SSPI";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
cmd.Parameters.AddWithValue("#Excursion_ID", Convert.ToInt32(mynew2));
cmd.Parameters.AddWithValue("#Excursion_date_ID", Convert.ToInt32(mynewnewstring));
cmd.Parameters.AddWithValue("#Name_kir", tx888.Text);
cmd.Parameters.AddWithValue("#MidName_kir", tx888_1.Text);
cmd.Parameters.AddWithValue("#LastName_kir", tx888_2.Text);
int added;
try
{
con.Open();
added = (int)cmd.ExecuteScalar();
lblproba.Text = "";
Tourist.Add(added);
lblproba.Text += Tourist.Count();
}
catch (Exception ex)
{
lblproba.Text += ex.Message;
}
finally
{
con.Close();
}
}
createReservation();
}
}
I call CreateReservationFunction AND i CREATE A NEW RESERVAION WITH THE ID OF THE USER WHO HAS MADE THE RESERVATION. wITH SELECT IDENTITY I TRY TO GET THE RESERVATION_ID of the reservation and here I get the exception "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack". So I wonder can this exception has something commn with the fact that in my solution exceptthe asp.net web projectI got library class in which I has .edmx file The entity framework model of my database and in my last form I don't use Ado,net but Entity framework
public void createReservation()
{
string insertSQL = "Insert INTO RESERVATIONS (User_ID) values (#User_ID) SELECT ##IDENTITY";
string connectionString = "Data Source = localhost\\SQLExpress;Initial Catalog=excursion;Integrated Security=SSPI";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
cmd.Parameters.AddWithValue("#User_ID", 9);
try
{
con.Open();
string added = cmd.ExecuteScalar().ToString();
createTouristReservation(added);
}
catch (Exception ex)
{
lblproba.Text+= ex.Message;
}
}
Don't use ##IDENTITY but SCOPE_IDENTITY and add a semicolon between the insert and the select.
string insertSQL = #"INSERT INTO Tourist (Excursion_ID, Excursion_date_ID, Name_kir,Midname_kir, Lastname_kir)
VALUES (#Excursion_ID, #Excursion_date_ID, #Name_kir,#Midname_kir, #Lastname_kir)
;SELECT CAST(scope_identity() AS int)";
I am trying to update the files in the table that I have created. I am using file uploader to insert my Excel file and upload it to the database. But currently my code creates a new database table each time a file is uploaded, which I don't want it to do. I want to just update/replace the whole file in database table. How do I do this?
This is my code:
private string GetConnectionString()
{
return System.Configuration.ConfigurationManager.ConnectionStrings["nConnectionString2"].ConnectionString;
}
private void CreateDatabaseTable(DataTable dt, string tableName)
{
string sqlQuery = string.Empty;
string sqlDBType = string.Empty;
string dataType = string.Empty;
int maxLength = 0;
StringBuilder sb = new StringBuilder();
sb.AppendFormat(string.Format("CREATE TABLE {0} (", tableName));
for (int i = 0; i < dt.Columns.Count; i++)
{
dataType = dt.Columns[i].DataType.ToString();
if (dataType == "System.Int32")
{
sqlDBType = "INT";
}
else if (dataType == "System.String")
{
sqlDBType = "NVARCHAR";
maxLength = dt.Columns[i].MaxLength;
}
if (maxLength > 0)
{
sb.AppendFormat(string.Format(" {0} {1} ({2}), ", dt.Columns[i].ColumnName, sqlDBType, maxLength));
}
else
{
sb.AppendFormat(string.Format(" {0} {1}, ", dt.Columns[i].ColumnName, sqlDBType));
}
}
sqlQuery = sb.ToString();
sqlQuery = sqlQuery.Trim().TrimEnd(',');
sqlQuery = sqlQuery + " )";
using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
{
sqlConn.Open();
SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn);
sqlCmd.ExecuteNonQuery();
sqlConn.Close();
}
}
private void LoadDataToDatabase(string tableName, string fileFullPath, string delimeter)
{
string sqlQuery = string.Empty;
StringBuilder sb = new StringBuilder();
sb.AppendFormat(string.Format("BULK INSERT {0} ", tableName));
sb.AppendFormat(string.Format(" FROM '{0}'", fileFullPath));
sb.AppendFormat(string.Format(" WITH ( FIELDTERMINATOR = '{0}' , ROWTERMINATOR = '\n' )", delimeter));
sqlQuery = sb.ToString();
using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
{
sqlConn.Open();
SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn);
sqlCmd.ExecuteNonQuery();
sqlConn.Close();
}
}
protected void btnImport_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
FileInfo fileInfo = new FileInfo(FileUpload1.PostedFile.FileName);
if (fileInfo.Name.Contains(".csv"))
{
string fileName = fileInfo.Name.Replace(".csv", "").ToString();
string csvFilePath = Server.MapPath("UploadExcelFile") + "\\" + fileInfo.Name;
//Save the CSV file in the Server inside 'MyCSVFolder'
FileUpload1.SaveAs(csvFilePath);
//Fetch the location of CSV file
string filePath = Server.MapPath("UploadExcelFile") + "\\";
string strSql = "SELECT * FROM [" + fileInfo.Name + "]";
string strCSVConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";" + "Extended Properties='text;HDR=YES;'";
// load the data from CSV to DataTable
OleDbDataAdapter adapter = new OleDbDataAdapter(strSql, strCSVConnString);
DataTable dtCSV = new DataTable();
DataTable dtSchema = new DataTable();
adapter.FillSchema(dtCSV, SchemaType.Mapped);
adapter.Fill(dtCSV);
if (dtCSV.Rows.Count > 0)
{
CreateDatabaseTable(dtCSV, fileName);
Label1.Text = string.Format("The table ({0}) has been successfully created to the database.", fileName);
string fileFullPath = filePath + fileInfo.Name;
LoadDataToDatabase(fileName, fileFullPath, ",");
Label1.Text = string.Format("({0}) records has been loaded to the table {1}.", dtCSV.Rows.Count, fileName);
}
else
{
Label1.Text = "File is empty.";
}
}
else
{
Label1.Text = "Unable to recognize file.";
}
}
}
The code that creates the tables should give an error when you run it if the tables already exists as you never drop them.
That said, one solution might be to add a check to see if the table already exists in the code that creates a new table; it should be something like:
IF OBJECT_ID('TABLE', 'U') IS NULLwhere TABLEit the name of the table that you want to add, so the code might look like:
sb.AppendFormat(string.Format("IF OBJECT_ID({0}, 'U') IS NULL CREATE TABLE {0} (", tableName));
Another, possibly better, option would be to run a query to check if the table exists before you run the CreateDatabaseTable(dtCSV, fileName);statement. You can do the check by executing something like IF OBJECT_ID('tableName', 'U') IS NULL SELECT 1 ELSE SELECT 0 (this would return 1 if the table doesn't exist), and then conditionally execute the CreateDatabaseTablestatement.
I am trying to learn how to use sql data adapter ... I have coded the following to check how it works ...
the problem is i want to retrieve values of 3 columns(DeptNo,DeptId,DeptName) of my database table "Sana" separately and display them in three separate text boxes ...
Through the code mentioned below I am able to retrieve the value of entire tuple of data base table together
what should I do to reach above mentioned result???
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection connect = new SqlConnection(ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand("Select DeptNo,DeptId,DeptName from Sana where DeptName='" + TextBox1.Text + "'", connect);
SqlDataAdapter myAdapter = new SqlDataAdapter(cmd);
DataSet MyDataSet = new DataSet();
myAdapter.Fill(MyDataSet, "Departments");
object[] rowVals = new object[3];
foreach (DataTable myTable in MyDataSet.Tables)
{
foreach (DataRow myRow in myTable.Rows)
{
foreach (DataColumn myColumn in myTable.Columns)
{
Response.Write(myRow[myColumn] + "\t");
}
}
}
}
}
foreach (DataRow myRow in MyDataSet.Tables[0].Rows)
{
TextBox1.Text = myRow["DeptNo"].ToString();
TextBox2.Text = myRow["DeptId"].ToString();
...
}
I have the following code:
using (SqlConnection cn = new SqlConnection(Connection.Instance.ConnectionString))
{
// Open the connection
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = cn;
cmd.CommandText = "Select Customers.CustomerID, Addresses.AddressCode, Addresses.FirstName, Addresses.LastName, Addresses.Address1, Addresses.City, Addresses.State, " +
"Addresses.Zip, Addresses.Home AS HomePhone, Addresses.Phone AS WorkPhone, Addresses.EmailAddress From Customers " +
"LEFT OUTER JOIN Addresses ON Addresses.ID=Customers.AddressID " +
"Where CustomerType IN ('HomeOwner', 'Home Owner') AND Customers.ResellerID=#ResellerID ";
cmd.Parameters.AddWithValue("#ResellerID", base.UserID);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet dsCustomer = new DataSet();
da.Fill(dsCustomer);
var customers = from c in dsCustomer.Tables[0].AsEnumerable().AsQueryable()
where c.Field<string>("CustomerID") == txtSearchCriteria.Text
select c;
dgCustomers.CurrentPageIndex = 0;
dgCustomers.DataSource = customers;
dgCustomers.DataBind();
}
catch (Exception e)
{
throw new Exception(e.Message + e.StackTrace);
}
finally
{
if ((cn != null) && (cn.State != ConnectionState.Closed))
cn.Close();
}
}
}
Which is giving me the error
AllowCustomPaging must be true and VirtualItemCount must be set for a DataGrid with ID 'dgCustomers' when AllowPaging is set to true and the selected data source does not implement ICollection. at System.Web.UI.WebControls.DataGrid.CreateControlHierarchy(Boolean useDataSource)
How do I convert this LINQ query so that it can be pagable?
Note: This is a simplified version of what I'm trying to do. I know in this example I could simply modify the SQL statement to include "And CustomerID=#CustomerID" and bypass LINQ completely. But, in the bigger picture, I can't do that.
The error message is clear, you need to implement your paging logic to take advantage from paging. BTW, to make your code to work just use a ICollection as DataSource, changing this line:
dgCustomers.DataSource = customers.ToList();