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);
}
Related
I have an ASP.Net app which transfers Excel rows to a SQL Server table and then they get processed by a stored procedure (TableA data gets formatted to TableB, then TableA gets truncated).
Both the app and the stored procedure work fine while debugging directly on the VS environment, but on the web deploy I get the following SQL Exception:
String or binary data would be truncated.
The statement has been terminated.
I've already changed the table schema to nvarchar(200) on every column, and turned ansi_warnings off on the stored procedure but nothing seems to affect the error. Again, this is only on the web deploy which only makes me think that the user permissions on the server side (every user logs in as NT AUTHORITY\NETWORK SERVICE on SQL).
This is the C# side of the app:
if (subeArchivo.HasFile)
{
var fechaYMD = DateTime.Now.ToString("yyyyMMdd");
var fechaHM = DateTime.Now.ToString("hhmm");
string path = string.Concat(Server.MapPath("~/archivoCargado/" + fechaHM + "_" + fechaYMD + "_" + subeArchivo.FileName));
subeArchivo.SaveAs(path);
DataTable dt = ExcelToDataTable(subeArchivo.FileBytes, cbEncabezado.Checked);
gridDT.DataSource = dt;
gridDT.DataBind();
try
{
string cadenaConn = ConfigurationManager.ConnectionStrings["cadenaSQL"].ConnectionString.ToString();
SqlConnection conn = new SqlConnection(cadenaConn);
SqlCommand cmd = new SqlCommand();
SqlBulkCopy bulkcopy = new SqlBulkCopy(cadenaConn);
SqlBulkCopyColumnMapping ID_USU_CAR = new SqlBulkCopyColumnMapping("ID_USU_CAR", "ID_USU_CAR");
bulkcopy.ColumnMappings.Add(ID_USU_CAR);
SqlBulkCopyColumnMapping RUT_DCT = new SqlBulkCopyColumnMapping("RUT_DCT", "RUT_DCT");
bulkcopy.ColumnMappings.Add(RUT_DCT);
SqlBulkCopyColumnMapping TIP_CON = new SqlBulkCopyColumnMapping("TIP_CON", "TIP_CON");
bulkcopy.ColumnMappings.Add(TIP_CON);
SqlBulkCopyColumnMapping ID_CON = new SqlBulkCopyColumnMapping("ID_CON", "ID_CON");
bulkcopy.ColumnMappings.Add(ID_CON);
SqlBulkCopyColumnMapping INI_BEN = new SqlBulkCopyColumnMapping("INI_BEN", "INI_BEN");
bulkcopy.ColumnMappings.Add(INI_BEN);
SqlBulkCopyColumnMapping FIN_BEN = new SqlBulkCopyColumnMapping("FIN_BEN", "FIN_BEN");
bulkcopy.ColumnMappings.Add(FIN_BEN);
SqlBulkCopyColumnMapping MON_CLP = new SqlBulkCopyColumnMapping("MON_CLP", "MON_CLP");
bulkcopy.ColumnMappings.Add(MON_CLP);
bulkcopy.DestinationTableName = "TMP_CAR_DCT_BEN";
bulkcopy.WriteToServer(dt);
lblCarga.Visible = true;
lblCarga.Text = "CARGA A SQL COMPLETADA";
lblSP.Visible = true;
lblSP.Text = "EJECUTANDO VALIDACIONES";
cmd.CommandText = "VAL_DCT_BEN_BETA2";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
lblSP.Text = "VALIDACIÓN COMPLETADA";
}
catch (Exception ex)
{
lblConfirma.Text = ex.Message.ToString();
}
try
{
lblRes.Visible = true;
connSQL.Open();
// PROCESO RESUMEN
SqlCommand selProc = connSQL.CreateCommand();
SqlDataAdapter adaptadorDatos1 = new SqlDataAdapter(selProc);
selProc.CommandText = "SELECT TOP 1 * FROM CON_PRO_BEN ORDER BY CAST(FEC_CAR AS DATETIME) DESC, HOR_CAR DESC";
selProc.CommandType = CommandType.Text;
DataTable tablaProcRes = new DataTable();
adaptadorDatos1.Fill(tablaProcRes);
gridProcRes.DataSource = tablaProcRes;
gridProcRes.DataBind();
gridProcRes.Visible = true;
connSQL.Close();
connSQL.Open();
// PROCESO DESCRIPTIVO
SqlCommand selProcDes = connSQL.CreateCommand();
SqlDataAdapter adaptadorDatos2 = new SqlDataAdapter(selProcDes);
selProcDes.CommandText = "SELECT * FROM CON_PRO_BEN_DES " +
"WHERE FEC_CAR = (SELECT MAX(FEC_CAR) FROM CON_PRO_BEN_DES) AND HOR_CAR = (SELECT MAX(HOR_CAR) FROM CON_PRO_BEN_DES) " +
"ORDER BY HOR_CAR DESC";
selProcDes.CommandType = CommandType.Text;
DataTable tablaProcResDes = new DataTable();
adaptadorDatos2.Fill(tablaProcResDes);
gridProcDes.DataSource = tablaProcResDes;
gridProcDes.DataBind();
gridProcDes.Visible = true;
connSQL.Close();
}
catch (Exception ex)
{
lblResQ.Text = ex.Message.ToString();
}
}
else
lblError.Visible = true;
lblError.Text = "Incidencias en la carga, reintentar.";
I am facing difficulty on writing logic to insert data into the database from some array. My requirement is if the data already exist in SQL insert query should not be executed. only when that data does not exist in database the insert query has to be executed where data will be inserted. I have tried a lot please find my code below.
public void writetodatabase()
{
//SQL connection String
SqlConnection cnn = new SqlConnection(#"Data Source=ABDUL-TPS\TPSSQLSERVER;Initial Catalog=Automation;Integrated Security=True");
// Open Connection to sql
cnn.Open();
// Declare a DataTable which will contain the result from SQL query
DataTable DT = new DataTable();
for(int m =0; m < globalZoho_Names.Length; m++)
{
string query1 = "select * from tbl_Zoho_data where col_Zoho_SKU like '" + globalZoho_SKU[m] + "'";
SqlCommand cmd1 = new SqlCommand(query1, cnn);
SqlDataReader reader1 = cmd1.ExecuteReader();
while (reader1.Read())
{
string zohosku = reader1["col_Zoho_SKU"].ToString();
if (zohosku == null)
{
string ItemName = reader1["col_item_name"].ToString();
string insert1 = "insert into tbl_zOHO_DATA values ('" + globalZoho_SKU[m] + "','" + globalZoho_Names[m] + "')";
SqlDataAdapter DA_insert = new SqlDataAdapter(insert1, cnn);
DA_insert.Fill(DT);
Label1.Text = "Khulja Sim Sim";
}
}
reader1.Close();
}
}
I want the code to check for the values first into the database and then insert only those values which do not exist in the database.
Im having a lot of trouble understanding OLEDB, im particularly struggling to get information to save to the database this is my current code to attempt to save:
Note: i can load the information absolutely fine, and when i run this function my information appears in my listBox however upon closing the application it hasnt saved.
If you could help explain the problem that would be great
void Insert_New_Log(int startfloor, int endfloor, string currentAction)
{
OleDbConnection conn = new OleDbConnection(dbconnection);
OleDbCommand comm = new OleDbCommand(dbcommand, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
// adapter.UpdateCommand = builder.GetUpdateCommand();
conn.Open();
adapter.Fill(ds, "ElevatorTable");
conn.Close();
DataRow newRow = ds.Tables[0].NewRow();
newRow["ID"] = 0;
newRow["Date1"] = dateAndTime;
newRow["StartingFloor"] = startfloor;
newRow["EndFloor"] = endfloor;
newRow["Action"] = currentAction;
ds.Tables[0].Rows.Add(newRow);
DataSet dataSetChanges = ds.GetChanges();
try
{
adapter.Update(dataSetChanges, "ElevatorTable");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
ds.AcceptChanges();
//update Visible list
dbListBox.Items.Clear();
foreach (DataRow row in ds.Tables[0].Rows)
{
dbListBox.Items.Add(row["ID"] + "\t" + row["Date1"] + "\t" + row["StartingFloor"] + "\t" + row["EndFloor"] + "\t" + " (" + row["Action"] + ")");
}
}
ive since put a write line in and found this exception.
Exception thrown: 'System.Data.OleDb.OleDbException' in System.Data.dll
System.Data.OleDb.OleDbException (0x80040E14): Syntax error in INSERT INTO statement.
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(DataSet dataSet, String srcTable)
at System.Data.Common.DbDataAdapter.Update(DataSet dataSet)
at Elevator.Form1.Insert_New_Log(Int32 startfloor, Int32 endfloor, String currentAction) in C:\Users\Brads\Desktop\Elevator\Elevator\Form1.cs:line 197
you have closed the connection after filling the adapter. You need to either leave the connection open or re-open it.
adapter.Fill(ds, "ElevatorTable");
conn.Close();
Follow this by
conn.Open();
Does the user you have setup in the adapter have write permissions in the SQL database? Also you closed your connection before the update statement that will need to be open in order to write back.
void Insert_New_Log(int startfloor, int endfloor, string currentAction)
{
OleDbConnection conn = new OleDbConnection(dbconnection);
OleDbCommand comm = new OleDbCommand(dbcommand, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
// adapter.UpdateCommand = builder.GetUpdateCommand();
conn.Open();
adapter.Fill(ds, "ElevatorTable");
DataRow newRow = ds.Tables[0].NewRow();
newRow["ID"] = 0;
newRow["Date1"] = dateAndTime;
newRow["StartingFloor"] = startfloor;
newRow["EndFloor"] = endfloor;
newRow["Action"] = currentAction;
ds.Tables[0].Rows.Add(newRow);
DataSet dataSetChanges = ds.GetChanges();
ds.AcceptChanges();
try
{
adapter.Update(dataSetChanges, "ElevatorTable");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally { conn.Close(); }
//update Visible list
dbListBox.Items.Clear();
foreach (DataRow row in ds.Tables[0].Rows)
{
dbListBox.Items.Add(row["ID"] + "\t" + row["Date1"] + "\t" + row["StartingFloor"] + "\t" + row["EndFloor"] + "\t" + " (" + row["Action"] + ")");
}
}
I have this public DataTable that I am trying to run an sql query in, but the dang thing wont work...
public DataTable get_OrderTransaction_Master_ByOrderID(Int64 orderID)
{
cn = new SqlConnection(objCommon.IpcConnectionString);
cmd = new SqlCommand("select * from dbo.OrderTransaction_Master where orderID = " + orderID, cn);
cmd.CommandType = CommandType.Text;
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
I get a red line under get_OrderTransaction_Master_ByOrderID saying
Error 3 'OrderTransaction_Master.get_OrderTransaction_Master_ByOrderID(long)': not all code paths return a value C:\IPC\App_Code\OrderTransaction_Master.cs 32 22 http://localhost/ipc/
What Am I doing wrong?
The return type of your method is a DataTable, but you don't have a return statement in your method. You are also executing cmd.ExecuteNonQuery(), where you should be doing cmd.ExecuteReader() and loading a DataTable
public DataTable get_OrderTransaction_Master_ByOrderID(Int64 orderID)
{
DataTable dt = new DataTable();
using(var cn = new SqlConnection(objCommon.IpcConnectionString))
{
using(var cmd = new SqlCommand(
"select * from dbo.OrderTransaction_Master where orderID = " + orderID, cn))
{
cmd.CommandType = CommandType.Text;
cn.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
dt.Load(reader);
return dt;
}
}
}
}
I put the SqlConnection, SqlCommand and SqlDataReader in using statements. This will properly dispose of the objects (close the connections, etc) once the using statement is exited.
your return type is a DataTable but your function doesn't return anything.
2 things, change the function to void, or return a dataTable
This method will help you no end. It is my baby, and is a real beaut.
It accepts your SQLQuery as a parameter and returns a DataTable object:
public DataTable DBGetDataTable(string SQLQuery)
{
string MethodName = "public DataTable DBGetDataTable(string SQLQuery)";
DataTable Result = null;
SqlConnection SqlConnection = null;
SqlCommand SqlCommand = null;
try
{
string DatabaseName = "";
string ServerNameOrIP = "";
string DatabaseUserID = "";
string Password = "";
string ConnectionString = "database=" + DatabaseName + ";server=" + ServerNameOrIP + ";user ID=" + DatabaseUserID + ";PWD=" + Password + ";Connection Timeout=5000";
SqlConnection = new SqlConnection(ConnectionString);
SqlCommand = new SqlCommand(SQLQuery, SqlConnection);
SqlConnection.Open();
SqlDataReader SqlDataReader = SqlCommand.ExecuteReader();
if (SqlDataReader.HasRows)
{
DataTable Dt = new DataTable();
Dt.Load(SqlDataReader);
Result = Dt;
}
}
catch (Exception ex)
{
//Common.Exception(ClassName, MethodName, ex);
}
finally
{
SqlConnection.Close();
SqlConnection.Dispose();
SqlConnection = null;
SqlCommand.Dispose();
SqlCommand = null;
}
return Result;
}
Since your database credentials will be different to mine, you will need to supply values for the following variables within the above code:
string DatabaseName = "";
string ServerNameOrIP = "";
string DatabaseUserID = "";
string Password = "";
It is very resilient and it cleans up after itself very efficiently, and as such is designed for heavy database use.
Here is an example of it being used:
StringBuilder sbSQL = new StringBuilder();
sbSQL.AppendLine(" SET DATEFORMAT DMY");
sbSQL.AppendLine(" SELECT");
sbSQL.AppendLine(" TillPayment.TillPaymentId As Id");
sbSQL.AppendLine(" , TillPayment.TransactionGuid As TransactionCode");
sbSQL.AppendLine(" , TillPayment.Amount As Price");
sbSQL.AppendLine(" , TillPayment.DiscountPercentage");
sbSQL.AppendLine(" , TillPayment.Processed As ProcessedDate");
sbSQL.AppendLine(" , PaymentType.Name As PaymentType");
sbSQL.AppendLine(" , TillPayment.ItemType As Item");
sbSQL.AppendLine(" , TillUser.LoginCode As Login");
sbSQL.AppendLine(" , TillUser.Name As UserName");
sbSQL.AppendLine(" , TillPayment.TillName As Till");
sbSQL.AppendLine(" FROM");
sbSQL.AppendLine(" [tblTillPayment] TillPayment");
sbSQL.AppendLine(" INNER JOIN [tblPaymentType] PaymentType ON TillPayment.PaymentTypeId = PaymentType.PaymentTypeId");
sbSQL.AppendLine(" INNER JOIN [tblTillUser] TillUser ON TillPayment.TillLoginCode = TillUser.LoginCode");
int SelectedMonthFrom = GetMonthAsNumber(CboMonthReportMonth.SelectedItem.Text);
int SelectedYearFrom = int.Parse(CboMonthReportYear.SelectedItem.Text);
int SelectedMonthTo = SelectedMonthFrom == 12 ? 1 : SelectedMonthFrom + 1;
int SelectedYearTo = SelectedMonthTo == 1 ? SelectedYearFrom + 1: SelectedYearFrom;
sbSQL.AppendLine(" WHERE");
sbSQL.AppendLine(" Processed >= '01-" + SelectedMonthFrom + "-" + SelectedYearFrom + " 00:00'");
sbSQL.AppendLine(" AND Processed < '01-" + SelectedMonthTo + "-" + SelectedYearTo + " 00:00'");
sbSQL.AppendLine(" AND NOT(TillUser.LoginCode = '2503' or TillUser.LoginCode = '1453')");
sbSQL.AppendLine(" ORDER BY");
sbSQL.AppendLine(" Till");
sbSQL.AppendLine(" , Processed");
DataTable DtReport = DBGetDataTable(sbSQL.ToString());
Of course, your SQL query will differ from mine.
Notice, I have used a StringBuilder object, but if you're more comfortable writing directly to a string then you may do that instead.
You wrote
I still get the same erro Error 3
'OrderTransaction_Master.get_OrderTransaction_Master_ByOrderID(long)':
not all code paths return a value
C:\IPC\App_Code\OrderTransaction_Master.cs 33 22 http:// localhost/ipc/
from before
This suggests that thereis no default return value for the method called OrderTransaction get_OrderTransaction_Master_ByOrderID(long OrderId)
I'd imagine the method in question should look something like the following:
public OrderTransaction get_OrderTransaction_Master_ByOrderID(long OrderId)
{
string MethodName = "public OrderTransaction get_OrderTransaction_Master_ByOrderID(long OrderId)";
OrderTransaction Result = null;
try{
StringBuilder sbSQL = new StringBuilder();
sbSQL.AppendLine(" SELECT");
sbSQL.AppendLine(" *");
sbSQL.AppendLine(" FROM");
sbSQL.AppendLine(" dbo.OrderTransaction_Master");
sbSQL.AppendLine(" WHERE");
sbSQL.AppendLine(" OrderID = " + OrderID);
DataTable Dt = DBGetDataTable(sbSQL.ToString())
OrderTransaction OrderTransaction = new OrderTransaction(Dt);
Result = OrderTransaction;
}
catch(Exception ex)
{
//Common.Exception(ClassName,MethodName,ex);
}
return Result;
}
Please ask if you have any questions.
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