Handling 'NULL' and key constraints when inserting data from a gridview - c#

I'm trying to insert values into the database via gridview from a C# Windows application. I tried 2 different methods but neither seems to be working for me. The 2 type of code is shown below......
Assuming, even if the code below works.... I'm getting various errors regarding the primary key and foreign key constraints.......
Problem:
I have confactorID and macroID columns as integer with nullable in destination businesslogic table....... I'm not sure how to insert 'NULL' in these columns from the C# gridview tool...
Even if I give integer values as input there seems to be foreign key and primary key (duplication) constraint issues....
What do I need to change in my below code to resolve these issues.... I've been stuck with these problem for more than 8 hours... Any help is much appreciated.
Code type 1:
private void ADD_button_Click(object sender, EventArgs e)
{
try
{
using (SqlConnection con = new SqlConnection(sqlconn))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = con;
con.Open();
for (int i = 1; i < dataGridView.Rows.Count; i++)
{
string sql = #"INSERT INTO " + schemaName +"ERSBusinessLogic VALUES ("
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_ID"].Value + ", '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_Formula"].Value.ToString() + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_InputsCount"].Value + ",'"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_Inputs"].Value.ToString() + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value + ", "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value + ", '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_DataSeries"].Value.ToString() + "', '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_InputTimeDimensionValue"].Value.ToString() + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_InputTimeDimensionType"].Value + ", "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_GeographyDimensionID"].Value + ", "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_InputsUnitsIDs"].Value + ", '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_Type"].Value + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_PrivacyID"].Value + ", '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_LongDesc"].Value.ToString() + "', '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_InputSources"].Value.ToString() + "', '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_OutputName"].Value.ToString() + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_OutputUnitID"].Value + ", '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_OutputDestination"].Value.ToString() + "', '"
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_OutputTimeDimensionValue"].Value.ToString() + "', "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_OutputTimeDimensionType"].Value + ", "
+ dataGridView.Rows[i].Cells["ERSBusinessLogic_GroupID"].Value + ");";
if ((dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value == " ") && (dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value == null))
{
Convert.ToInt32(dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value = "NULL");
Convert.ToInt32 (dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value = "NULL");
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
else
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message);
}
finally
{
con.Close();
}
}
Code type 2:
private void ADD_button_Click(object sender, EventArgs e)
{
// Getting data from DataGridView
DataTable myDt = new DataTable();
myDt = GetDTfromDGV(dataGridView);
// Writing to sql
WriteToSQL(myDt);
}
private DataTable GetDTfromDGV(DataGridView dgv)
{
// Making our DataTable
DataTable dt = new DataTable();
foreach (DataGridViewColumn column in dgv.Columns)
{
dt.Columns.Add(column.Name, typeof(string));
}
// Getting data
foreach (DataGridViewRow dgvRow in dgv.Rows)
{
DataRow dr = dt.NewRow();
for (int col = 0; col < dgv.Columns.Count; col++)
{
dr[col] = dgvRow.Cells[col].Value;
}
dt.Rows.Add(dr);
}
// removing empty rows
for (int row = dt.Rows.Count - 1; row >= 0; row--)
{
bool flag = true;
for (int col = 0; col < dt.Columns.Count; col++)
{
if (dt.Rows[row][col] != DBNull.Value)
{
flag = false;
break;
}
}
if (flag == true)
{
dt.Rows.RemoveAt(row);
}
}
return dt;
}
private void WriteToSQL(DataTable dt)
{
using (SqlConnection con = new SqlConnection(sqlconn))
{
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con);
// Setting the database table name
sqlBulkCopy.DestinationTableName = "[AnimalProductsCoSD].[CoSD].[ERSBusinessLogic]";
// Mapping the DataTable columns with that of the database table
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[0].ColumnName, "ERSBusinessLogic_ID"));
Convert.ToString(sqlBulkCopy.ColumnMappings.Add(dt.Columns[1].ColumnName, "ERSBusinessLogic_Formula"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[2].ColumnName, "ERSBusinessLogic_InputsCount"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[3].ColumnName, "ERSBusinessLogic_Inputs"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[4].ColumnName, "ERSBusinessLogic_ConvFactorID"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[5].ColumnName, "ERSBusinessLogic_MacroID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[6].ColumnName, "ERSBusinessLogic_DataSeries"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[7].ColumnName, "ERSBusinessLogic_InputTimeDimensionValue"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[8].ColumnName, "ERSBusinessLogic_InputTimeDimensionType"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[9].ColumnName, "ERSBusinessLogic_GeographyDimensionID"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[10].ColumnName, "ERSBusinessLogic_InputsUnitsIDs"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[11].ColumnName, "ERSBusinessLogic_Type"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[12].ColumnName, "ERSBusinessLogic_PrivacyID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[13].ColumnName, "ERSBusinessLogic_LongDesc"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[14].ColumnName, "ERSBusinessLogic_InputSources"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[15].ColumnName, "ERSBusinessLogic_OutputName"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[16].ColumnName, "ERSBusinessLogic_OutputUnitID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[17].ColumnName, "ERSBusinessLogic_OutputDestination"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[18].ColumnName, "ERSBusinessLogic_OutputTimeDimensionValue"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[19].ColumnName, "ERSBusinessLogic_OutputTimeDimensionType"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[20].ColumnName, "ERSBusinessLogic_GroupID"));
con.Open();
sqlBulkCopy.WriteToServer(dt);
}
}
Thanks

First of all check your database table, columns that keeps IDs from another tables must allow null value like so:
And if your table ID is Identity column with auto increment you don't need to write ID, table automatically add ID.
If everything ok then try to do like so:
private DataTable GetDTfromDGV(DataGridView dgv)
{
// Macking our DataTable
DataTable dt = new DataTable();
//Another way to add columns
dt.Columns.AddRange(new DataColumn[5]
{
//new DataColumn("table_ID", typeof(string)), if table_ID is not Identity column with auto increment then uncomment
new DataColumn("sql_col2", typeof(string)),
new DataColumn("sql_col3", typeof(string)),
new DataColumn("sql_col4", typeof(string)),
new DataColumn("Table_2_ID", typeof(int)),
new DataColumn("Table_3_IDt", typeof(int))
});
// Getting data
foreach (DataGridViewRow dgvRow in dgv.Rows)
{
DataRow dr = dt.NewRow();
for (int col = 1; col < dgv.Columns.Count; col++) //if table_ID is not Identity column with auto increment then start with 0
{
dr[col - 1] = dgvRow.Cells[col].Value == null ? DBNull.Value : dgvRow.Cells[col].Value;
}
dt.Rows.Add(dr);
}
// removing empty rows
....
return dt;
}
private void WriteToSQL(DataTable dt)
{
string connectionStringSQL = "Your connection string";
using (SqlConnection sqlConn = new SqlConnection(connectionStringSQL))
{
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConn);
// Setting the database table name
sqlBulkCopy.DestinationTableName = "Table_1";
// Mapping the DataTable columns with that of the database table
//sqlBulkCopy.ColumnMappings.Add(dt.Columns[0].ColumnName, "table_ID"); table_ID is Identity column with auto increment
sqlBulkCopy.ColumnMappings.Add(dt.Columns[0].ColumnName, "sql_col2");
sqlBulkCopy.ColumnMappings.Add(dt.Columns[1].ColumnName, "sql_col3");
sqlBulkCopy.ColumnMappings.Add(dt.Columns[2].ColumnName, "sql_col4");
sqlBulkCopy.ColumnMappings.Add(dt.Columns[3].ColumnName, "Table_2_ID");
sqlBulkCopy.ColumnMappings.Add(dt.Columns[4].ColumnName, "Table_3_ID");
sqlConn.Open();
sqlBulkCopy.WriteToServer(dt);
}
}
I tried and that's what I got:

You could use parameterized query.
For example:
var sqlcommand = new SqlCommand
{
CommandText = "INSERT INTO TABLE(Column1,Column2) VALUES(#Column1Value,#Column2Value)"
};
var param1 = new SqlParameter("#Column1Value", SqlDbType.Int)
{
Value = (String.IsNullOrWhiteSpace(dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value)) ? DBNull.Value: (object)(dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value)
};
var param2 = new SqlParameter("#Column2Value", SqlDbType.Int)
{
Value = (String.IsNullOrWhiteSpace(dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value)) ? DBNull.Value : (object)dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value)
};
sqlcommand.Parameters.Add(param1);
sqlcommand.Parameters.Add(param2);

If you use method 1 that you tried, you'll probably want to create SqlParameter objects and parameterize your query. Refer to this SO post: Right syntax of SqlParameter. That being said, you just want to get it to work first I'm sure. You could check the value of the DataGridViewCell's Value property for the convFactorID and macroID. If either of these are null, then you can assign a string the text "NULL". For brevity, I've used the C# conditional operator (https://msdn.microsoft.com/en-us/library/ty67wk28.aspx). This is one way you might do what I'm describing:
string convFactorIDText = (dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value == null) ? "NULL" : dataGridView.Rows[i].Cells["ERSBusinessLogic_ConvFactorID"].Value.ToString();
string macroIDText = (dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value == null) ? "NULL" : dataGridView.Rows[i].Cells["ERSBusinessLogic_MacroID"].Value.ToString();
Then alter you SQL to include the string variables that contain either a actual value or NULL.
string sql = string.Format(#"INSERT INTO {0}.ERSBusinessLogic VALUES ({1}, '{2}', {3}, {4}, {5}, {6}"),
schemaName,
dataGridView.Rows[i].Cells["ERSBusinessLogic_ID"].Value,
dataGridView.Rows[i].Cells["ERSBusinessLogic_Formula"].Value.ToString(),
dataGridView.Rows[i].Cells["ERSBusinessLogic_InputsCount"].Value,
dataGridView.Rows[i].Cells["ERSBusinessLogic_Inputs"].Value,
convFactorIDText,
macroIDText
// and so forth
);

Related

Copying tables among databases

Let's say I want to copy all tables with their complete data from one database to another without specifically knowing detailed information about them(column count, data types...). The user would input a connection string to his database, and all data from it would be copied to an internal DB.
I tried to achieve it by using SqlConnection and writing direct T-SQL queries and managed to write a script that creates empty tables in Internal database with correct columns:
string createDestinationTableQuery = "create table " + schemaName + ".[" + tableName + "](";
DataTable ColumnsDT = new DataTable();
string getTableColumnDataQuery = "SELECT * FROM "+originalDBName+".INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'" + tableName +"'";
SqlCommand getTableColumnDataCommand = new SqlCommand(getTableColumnDataQuery, originalCon);
SqlDataAdapter TableDA = new SqlDataAdapter(getTableColumnDataCommand);
TableDA.Fill(ColumnsDT);
for (int x = 0; x < ColumnsDT.Rows.Count; x++)
{
createDestinationTableQuery += "[" + ColumnsDT.Rows[x].ItemArray[3].ToString() + "] " + "[" + ColumnsDT.Rows[x].ItemArray[7].ToString() + "], ";
}
createDestinationTableQuery = createDestinationTableQuery.Remove(createDestinationTableQuery.Length - 2);
createDestinationTableQuery += " )";
SqlCommand createDestinationTableCommand = new SqlCommand(createDestinationTableQuery, destinationCon);
createDestinationTableCommand.ExecuteNonQuery();
Console.WriteLine("Table " + schemaName + "." + tableName + " created succesfully!");
However, I am struggling with data insertion as the following code simply doesn't work:
DataTable dataTable = new DataTable();
string getTableDataquery = "select * from " + originalTableWithSchema;
SqlCommand getTableDataCommand = new SqlCommand(getTableDataquery, originalCon);
SqlDataAdapter da = new SqlDataAdapter(getTableDataCommand);
da.Fill(dataTable);
for (int x = 0; x < dataTable.Rows.Count; x++)
{
string insertQuery = "insert into " + schemaName + ".["+tableName+"](" ;
string values = "VALUES(";
for (int y = 0; y < dataTable.Columns.Count; y++)
{
insertQuery += dataTable.Columns[y].ColumnName + ", ";
values += dataTable.Rows[x].ItemArray[y].ToString() + ", ";
}
insertQuery = insertQuery.Remove(insertQuery.Length - 2);
insertQuery += " )";
values = values.Remove(values.Length - 2);
values += " )";
insertQuery += " " + values;
SqlCommand insertCommand = new SqlCommand(insertQuery, destinationCon);
insertCommand.ExecuteNonQuery();
}
da.Dispose();
How can I correctly Achieve this functionality? I was thinking of maybe scrapping all the code and using SMO instead?
If you are only looking to copy the data (because you have structure creation already working), then you could use DataTable to hold the data in a non-dbms specific structure, and a DataAdapter to generate the dbms specific insert statements. Here is an excerpt from code I wrote a while ago to copy data from Access to MySQL:
List<string> tableNames = new List<string>();
try
{
// Open connect to access db
sourceConn.Open();
// Build table names list from schema
foreach (DataRow row in sourceConn.GetSchema("Tables").Select("table_type = 'TABLE'"))
tableNames.Add(row["table_name"].ToString());
}
catch (Exception ex)
{
throw ex;
}
finally
{
if(sourceConn.State != ConnectionState.Closed)
sourceConn.Close();
}
foreach (string table in tableNames)
{
//Get all table data from Access
string query = string.Format("SELECT * FROM {0}", table);
DataTable accessTable = new DataTable(table);
try
{
sourceConn.Open();
System.Data.OleDb.OleDbCommand accessSqlCommand = new System.Data.OleDb.OleDbCommand(query, accessConn);
System.Data.OleDb.OleDbDataReader reader = (System.Data.OleDb.OleDbDataReader)accessSqlCommand.ExecuteReader();
// Load all table data into accessTable
accessTable.Load(reader);
}
catch(Exception ex)
{
throw ex;
}
finally
{
if(sourceConn.State != ConnectionState.Closed)
sourceConn.Close();
}
// Import data into MySQL
accessTable.AcceptChanges();
// The table should be empty, so set everything as new rows (will be inserted)
foreach (DataRow row in accessTable.Rows)
row.SetAdded();
try
{
destConn.Open();
MySql.Data.MySqlClient.MySqlDataAdapter da = new MySql.Data.MySqlClient.MySqlDataAdapter(query, mySqlConn);
MySql.Data.MySqlClient.MySqlCommandBuilder cb = new MySql.Data.MySqlClient.MySqlCommandBuilder(da);
da.InsertCommand = cb.GetInsertCommand();
// Update the destination table 128 rows at a time
da.UpdateBatchSize = 128;
// Perform inserts (and capture row counts for output)
int insertCount = da.Update(accessTable);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if(destConn.State != ConnectionState.Closed)
destConn.Close();
}
}
This could certainly be more efficient, but I wrote it for a quick conversion. Also, since this is copied and pasted you may need to tweak it. Hope it helps.
It might be worth thinking about using a linked server. Once a linked server is defined in the destination server, a table can be created and automatically filled with data using a SELECT…INTO statement.
Query executed in destination server database:
SELECT * INTO NewTableName FROM
SourceServername.SourceDatabasename.dbo.SourceTableName

C# datagrid not populating and no error

My first problem is that i have a method private void FillGeneralLedger(), i put the method in a button on click event to fill a datagridview dgvGeneralLedger my problem is when i run i am not getting an error and the dgv is remaining empty.
My Second problem is i would like to use the same connection but have 5 commands all the same just different account numbers eg in the example below the account below is '8200030' i would like to do the same for '8200031','8200032'
private void FillGeneralLedger()
{
SqlConnection conn = new SqlConnection(sConnectionString);
try
{
DataSet dataset = new DataSet();
SqlCommand command = new SqlCommand("Select Ddate as Date" +
", etype" +
", Refrence" +
", linkacc as ContraAcc" +
", Description" +
", sum(case when amount > 0 then amount else 0 end) as Debits" +
", sum(case when amount < 0 then amount else 0 end) as Credits" +
", sum(amount) as Cumulative" +
" FROM dbo.vw_LedgerTransactions " +
" WHERE accnumber = '8200030'" +
" AND DDate BETWEEN '2016-04-01 00:00:00' AND '2016-04-30 00:00:00'" +
" AND DataSource = 'PAS11CEDCRE17'" +
" group by Ddate, etype, Refrence, linkacc, Description, Amount", conn);
SqlDataAdapter adapter = new SqlDataAdapter(command);
conn.Open();
command.ExecuteNonQuery();
adapter.Fill(dataset);
if (dataset.Tables[0].Rows.Count != 0)
{
lstGeneralLedger = new List<ReportDataClasses.GeneralLedger>();
foreach (DataRow row in dataset.Tables[0].Rows)
{
ReportDataClasses.GeneralLedger newGeneralLedger = new ReportDataClasses.GeneralLedger();
newGeneralLedger.Ddate = row[0].ToString();
newGeneralLedger.etype = row[1].ToString();
newGeneralLedger.refrence = row[2].ToString();
newGeneralLedger.linkacc = row[3].ToString();
newGeneralLedger.Description = row[4].ToString();
newGeneralLedger.debit = decimal.Parse(row[5].ToString());
newGeneralLedger.credit = decimal.Parse(row[6].ToString());
newGeneralLedger.cumulative = decimal.Parse(row[7].ToString());
lstGeneralLedger.Add(newGeneralLedger);
}
dgvGeneralLedger.DataSource = dataset;
dgvGeneralLedger.Columns[0].Visible = false;
pdfCreator.AddGeneralLedgerPage(lstGeneralLedger, 1);
}
}
catch (Exception ex)
{
MessageBox.Show("Application Error. err:" + ex.ToString());
}
finally
{
conn.Close();
}
}
Why do you use a DataSet when you only need a single DataTable, this doesn't make any sense. Just use one DataTable:
DataTable dataTableSource = new DataTable();
adapter.Fill(dataTableSource);
// .. cotinue your code
dgvGeneralLedger.DataSource = dataTableSource;
Account Number issue:
You can use SqlParameter instead of hard-coding the value. Like this:
command.Parameters.AddWithValue("#acc", "8200030");
dataTableSource.Load(command.ExecuteReader())
// .. store results ..
// second account
command.Parameters["#acc"].Value = "8200031";
dataTableSource.Load(command.ExecuteReader())
// continue with the rest
But you need to change your query to be like this:
"... WHERE accnumber = #acc ...."

Using DataTable.update() does not add entries to my SQL Server database in one method but does in another

I have a method (AddRowToSQLTable()) that is passed a row, it then creates a row array containing that row and then passes it to DataTable.update().
This works fine. The SQL Server is updated and the next time I run (debug) the program the new data is present.
Another method (AddStock()) uses a similar structure but does not work.
The difference being that I am passing a data table in Update() not a Row[] however no exception is thrown just nothing is updated/added on the server.
Can someone please explain what exactly is going on and why these differ? I would like to know this even if the solution is to use a different structure to achieve what I want so I know for the future and have a better understanding.
To Note:
I have tested to ensure the DataTable being passed contains records. The DataTable is of the same format as the target SQL Server table.
I have also tried SqlBulkCopy and encounter the same problem.
Many thanks!
private DataTable StockAdditions;
public void PrepareStockQuantitiesForAdding()
{
if (StockAdditions != null)
{
StockAdditions.Clear();
}
StockAdditions = StockQuantitiesTable.Clone();
int Count = 0;
DataRow RowToAdd = StockQuantitiesTable.NewRow();
DataView AreaIDs = new DataView(AreaTable);
DataView Conditions = new DataView(ConditionsTable);
int AreaID;
string ConditionCode;
foreach (DataRow Row in SessionSKUScanned.Rows)
{
if (Row["Serial Number"].ToString() == "")
{
Conditions.RowFilter = "([Name] = '" + Row["Condition"] + "')";
ConditionCode = Conditions[0][2].ToString();
AreaIDs.RowFilter = "([StorageAreaName] = '" + Row["Area"] + "')";
AreaID = Convert.ToInt32(AreaIDs[0][0]);
DataView StockQuantities = new DataView(StockQuantitiesTable);
StockQuantities.RowFilter = "([QuantityID] = '" + AreaID + "-" + Row["SKU"] + "-" + ConditionCode + "')";
if (StockQuantities.Count > 0)
{
StockQuantities[0][3] = Convert.ToInt32(StockQuantities[0][3]) + 1;
RowToAdd["QuantityID"] = AreaID + "-" + Row["SKU"] + "-" + ConditionCode;
RowToAdd["SKU"] = Row["SKU"];
RowToAdd["AreaID"] = AreaID;
RowToAdd["Quantity"] = StockQuantities[0][3] = Convert.ToInt32(StockQuantities[0][3]) + 1;
RowToAdd["Condition"] = Row["Condition"];
}
else
{
RowToAdd["QuantityID"] = AreaID + "-" + Row["SKU"] + "-" + ConditionCode;
RowToAdd["SKU"] = Row["SKU"];
RowToAdd["AreaID"] = AreaID;
RowToAdd["Quantity"] = 1;
RowToAdd["Condition"] = Row["Condition"];
}
Count++;
}
else
{
RowToAdd["QuantityID"] = Row["Serial Number"];
RowToAdd["SKU"] = Row["SKU"];
AreaIDs.RowFilter = "([StorageAreaName] = '" + Row["Area"] + "')";
RowToAdd["AreaID"] = Convert.ToInt32(AreaIDs[0][0]);
RowToAdd["Quantity"] = 1;
RowToAdd["Condition"] = Row["Condition"];
Count++;
}
StockQuantitiesTable.ImportRow(RowToAdd);
MessageBox.Show(RowToAdd[0].ToString());
StockAdditions.ImportRow(RowToAdd);
}
}
private void AddRowToSQLTable(DataRow Row, string SQLTableName)
{
DataRow[] Rows = new DataRow[1];
Rows[0] = Row;
SqlConnection SQLConn = new SqlConnection(ConfigurationManager.ConnectionStrings["eCommStock.Properties.Settings.Demo_SiteConnectionString"].ConnectionString);
SQLConn.Open();
SqlDataAdapter daUpdateTable = new SqlDataAdapter("Select * From " + SQLTableName, SQLConn);
SqlCommandBuilder SQLcmdBuilder = new SqlCommandBuilder(daUpdateTable);
daUpdateTable.Update(Rows);
SQLConn.Close();
}
public void AddStock()
{
SqlConnection SQLConn = new SqlConnection(ConfigurationManager.ConnectionStrings["eCommStock.Properties.Settings.Demo_SiteConnectionString"].ConnectionString);
SQLConn.Open();
SqlDataAdapter daUpdateTable = new SqlDataAdapter("Select * From StockQuantities", SQLConn);
SqlCommandBuilder SQLcmdBuilder = new SqlCommandBuilder(daUpdateTable);
daUpdateTable.Update(StockAdditions);
SQLConn.Close();
}
It doesn't work because RowToAdd.RowState is Detached. I don't like it, but the following is a quick and dirty solution, before importing the row to StockAdditions, make sure the row is in Added state, later you can "detach" the row again.
StockQuantitiesTable.Rows.Add(RowToAdd);
StockAdditions.ImportRow(RowToAdd);
StockQuantitiesTable.Rows.Remove(RowToAdd);

C# SQL Insert with a very large number of parameters

I have had a problem for a few days and nothing online seems to do it.
I have an SQL table that has 150 columns. I am reading data from an ODBC connection and I want to insert that data into the SQL table. Basically duplicate the ODBC table as SQL.
My problem is that if I put everything in a string and insert it I face a hell of a time with escape characters and exceptions that I can't figure out.
Is there a way to parametrize my insert values that doesn't involve me naming each and every on of them separatly.
This is what I have right now. Also, if anyone knows an easier way to move an ODBC table to an SQL form please let me know
private void fillTable(string tableName)
{
String query = "SELECT * FROM " + tableName;
OdbcCommand command = new OdbcCommand(query, Program.myConnection);
OdbcDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
int columnCount = reader.FieldCount;
for (int i = 0; i < columnCount; i++)
{
SqlCommand sCommand = new SqlCommand("ALTER TABLE " + tableName + " ADD " + reader.GetName(i) + " varchar(MAX)", Program.myConnection2);
sCommand.ExecuteNonQuery();
}
string row="";
while (!reader.IsClosed)
{
try
{
row = "";
reader.Read();
for (int i = 0; i < columnCount; i++)
{
if (reader != null)
{
if (reader.GetString(i).Contains('\''))
{
Console.WriteLine("REPLACED QUOT");
String s = reader.GetString(i).Replace("\'", "A");
Console.WriteLine(s);
row += s;
}
else
{
row += "\'" + reader.GetString(i).Trim() + "\',";
}
// Console.WriteLine("FILLER: " + reader.GetString(i));
}
//Console.WriteLine(row);
}
//Console.WriteLine();
row = row.Substring(0, row.Length - 1);
SqlCommand insertCommand = new SqlCommand("INSERT INTO " + tableName + " VALUES(\'1\'," + row + ")", Program.myConnection2);
insertCommand.ExecuteNonQuery();
}
catch (SqlException exp)
{
Console.WriteLine(exp.StackTrace);
Console.WriteLine(row);
// this.Close();
}
}
Program.myConnection2.Close();
}
You can write a method that creats parameter names automatically, adds it to command, and returns the name so that you can use it in the query:
private int _paramCounter = 1;
private string CreateParameter(SqlCommand command, object value) {
string name = "#P" + _paramCounter.ToString();
_paramCounter++;
command.Parameters.AddWithValue(name, value);
return name;
}
Usage:
row += CreateParameter(insertCommand, reader.GetString(i).Trim()) + ",";
Note that you need to create the command object before you loop through the columns. Also, although not needed, you might want to reset the _paramCounter for each row, otherwise the parameter names get longer in the end.

How to ignore the empty cell in the GridView

I have a GridView and Edit link for each row. I can click on Edit and fill data in the cells of GridView and can Update the GridView row and the corresponding table in the database is also updated.
I have a save button, which on_click reads each and every row, column by column and perform some action.
The function works fine if all the cell in the GridView has some data filled in it. If the cell in the GridView is empty, it gives and error : Input String is not in the correct format.
The code I have tried is :
protected void SAVE_GRID_Click(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView2.Rows)
{
string Loc = row.Cells[1].Text;
string strg = "SELECT Location_Type FROM Quantity WHERE Locations='" + Loc + "'";
SqlCommand com = new SqlCommand(strg, con);
con.Open();
SqlDataReader sdr = com.ExecuteReader();
while (sdr.Read())
{
Loctype.Text = sdr[0].ToString().Trim();
}
con.Close();
for (int i = 1; i < GridView2.Columns.Count; i++)
{
String header = GridView2.Columns[i].HeaderText;
string str = "SELECT Profile_Type FROM Profile_Tooltip WHERE Profile_Name='"+header+"'";
SqlCommand cmd = new SqlCommand(str,con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
profiletype.Text = dr[0].ToString().Trim();
}
con.Close();
if (!string.IsNullOrEmpty(row.Cells[i + 1].Text.Trim()))
{
int n = Convert.ToInt16(row.Cells[i + 1].Text);
//int n = int.Parse(row.Cells[i].Text);
for (int m = Asset_List.Items.Count - 1; m >= 0; m--)
{
Asset_List.Items.Remove(Asset_List.Items[m]);
}
for (int j = 1; j <= n; j++)
{
Asset_List.Items.Add(string.Concat(profiletype.Text, j));
}
for (int k = 0; k <= Asset_List.Items.Count - 1; k++)
{
com = new SqlCommand("INSERT INTO " + Label3.Text + " VALUES ('" + Loctype.Text + "','" + Loc + "','" + header + "','" + Asset_List.Items[k] + "')", con);
con.Open();
com.ExecuteNonQuery();
con.Close();
}
}
}
}
SqlCommand comd = new SqlCommand("SELECT * FROM " + Label3.Text + "", con);
SqlDataAdapter da = new SqlDataAdapter(comd);
DataTable dt = new DataTable();
da.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
I want to check if the cell is empty, if empty I want to increment to next cell without performing any action for the empty cell.
Kindly help me solve this problem. Thank you.
just use trim and sting function
if (!string.IsNullOrEmpty(row.Cells[i].Text.Trim() ) )
you need to check here
int n = Convert.ToInt16(row.Cells[i + 1].Text);
check the string is convertible to integer or not using parse or tryparse methods of framework
short n = 0;
if(Int16.TryParse(row.Cells[i + 1].Text,out n);)
{
//perform function and user n here now
}
The line that sticks out the most to me is this one:
int n = Convert.ToInt16(row.Cells[i + 1].Text);
I usually use something like this to avoid exceptions:
int n = 0;
bool didParse = Int16.TryParse(row.Cells[i + 1].Text, out n);
if (didParse)
{
//add code here
}
Your error might be an exception being thrown because your cell text is empty or perhaps even null.

Categories

Resources