Well I produce code which takes the values from the database and creates XML files, but I stack on how to modify my code in order to avoid the empty cells from the column VALUES, also I need to select the data from the column VALUES where the column SELECT is 1. Can you please help me with examples? Thank you in advance .
code
public DataSet produceFieldsXml(int langID, int presID)
{
SqlConnection con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["beta"].ConnectionString;
SqlDataAdapter da = new SqlDataAdapter(#"SELECT IsubField.ID,IsubField.SUBJECT_ID as SUBJECTID,IsubField.VALUE AS DSCR,IsubField.FIELD_TYPE_ID, PFTT.VALUE AS TITLE
FROM I_SUBJECT_FIELD IsubField, P_FIELD_TYPE_TITLE PFTT
WHERE IsubField.PRESENTATION_ID = " + presID + #"
AND IsubField.LANGUAGE_ID = " + langID + #"
AND PFTT.FIELD_TYPE_ID = IsubField.FIELD_TYPE_ID
AND PFTT.LANGUAGE_ID = " + langID + #"
ORDER BY IsubField.SUBJECT_ID", con);
DataSet ds = new DataSet();
da.Fill(ds, "FieldItem");
ds.Tables[0].Columns.Add("SEQ", typeof(Int64));
DataSet dsNew = new DataSet();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
SqlDataAdapter daII = new SqlDataAdapter(#"SELECT CATEGORY_ID FROM I_SUBJECT WHERE ID = " + Convert.ToInt32(ds.Tables[0].Rows[i]["SUBJECTID"].ToString().Trim()) + "", con);
DataSet dsa = new DataSet();
daII.Fill(dsa, "FieldItem");
dsNew.Merge(dsa);
}
DataSet dsaa = new DataSet();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
SqlDataAdapter daII = new SqlDataAdapter(#"SELECT SEQ FROM P_CATEGORY_FIELD WHERE CATEGORY_ID = " + Convert.ToInt32(dsNew.Tables[0].Rows[i]["CATEGORY_ID"].ToString().Trim()) + " AND FIELD_ID = " + Convert.ToInt32(ds.Tables[0].Rows[i]["FIELD_TYPE_ID"].ToString().Trim()) + "", con);
daII.Fill(dsaa, "FieldItem");
ds.Tables[0].Rows[i]["SEQ"] = dsaa.Tables[0].Rows[0]["SEQ"];
}
for (int i = 0; i > dsaa.Tables[0].Rows.Count; i++)
{
ds.Tables[0].Rows[i]["SEQ"] = dsaa.Tables[0].Rows[0]["SEQ"];
}
dsaa.WriteXml(Server.MapPath("~/") + "ZipFiles\\" + "new.xml");
return ds;
}
If I were you I'd really try to learn more SQL, because I'm pretty sure those three queries above can be one query given the right joins. Unfortunately we cannot help you right now, unless you show us what I_SUBJECT_FIELD, P_FIELD_TYPE_TITLE, I_SUBJECT and P_CATEGORY_FIELD look like and how they're related.
Because this is simply very bad:
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
SqlDataAdapter daII = new SqlDataAdapter(#"SELECT CATEGORY_ID FROM I_SUBJECT WHERE ID = " + Convert.ToInt32(ds.Tables[0].Rows[i]["SUBJECTID"].ToString().Trim()) + "", con);
}
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
SqlDataAdapter daII = new SqlDataAdapter(#"SELECT SEQ FROM P_CATEGORY_FIELD WHERE CATEGORY_ID = " + Convert.ToInt32(dsNew.Tables[0].Rows[i]["CATEGORY_ID"].ToString().Trim()) + " AND FIELD_ID = " + Convert.ToInt32(ds.Tables[0].Rows[i]["FIELD_TYPE_ID"].ToString().Trim()) + "", con);
}
Those queries get executed numerous times and at most they should be executed once (bit trickier in the second case, but not impossible), and in fact they really should be part of the main query (provided the tables are set up correctly).
An even bigger headscratcher is this:
for (int i = 0; i > dsaa.Tables[0].Rows.Count; i++)
{
ds.Tables[0].Rows[i]["SEQ"] = dsaa.Tables[0].Rows[0]["SEQ"];
}
...since that is exactly the same line as in the previous for-loop.
Once you manage to create a single query it will be far easier to convert that data into XML.
Also look into encapsulating code in using statements.
Related
I am using C# to create a windows form.
I am trying to set a condition statement for a particular value that is retrieved from my database by the onclick of a button. The datatype of the column is 'integer'.
Below is my code:
string checkquantity = "SELECT `inventory_item`.`Item_Quantity_Available`FROM `inventory_item` , `patient`, `out_treatment`WHERE `inventory_item`.`Item_ID` = `out_treatment`.`Inventory_ID`AND `patient`.`Patient_ID` = `out_treatment`.`Patient_ID`AND `out_treatment`.`Patient_ID`= '" + pid + "' ";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
MySqlDataAdapter selectdata = new MySqlDataAdapter(checkquantity, connect);
DataTable selecttable = new DataTable();
selectdata.Fill(selecttable);
DataSet ds = new DataSet();
selectdata.Fill(selecttable);
selectdata.Fill(ds);
int i = ds.Tables[0].Rows.Count;
if ( i <= 0)
{
MessageBox.Show("Out of Stock");
}
I'm new with c#.
I don't think the int i = ds.Tables[0].Rows.Count; is the right way.
Any help is much appreciated.
First of all, like #Flydog57 said, you should not concatenate your sql query. The best way is to use parameters, for example:
string checkquantity = "SELECT i.Item_Quantity_Available " +
" FROM inventory_item i JOIN out_treatment t ON i.Item_Id = t.Inventory_ID " +
" JOIN patient p ON t.Patient_ID = p.PatiendID " +
" WHERE t.Patient_ID = #Patiend_ID";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
// set the parameter value
selectout.Parameters.AddWithValue("#Patiend_ID", patient_id_value);
MySqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
{
if ((int)rdr["Item_Quantity_Available"] == 0)
MessageBox.Show("Out of Stock");
}
In second place, you could use a MySqlDataReader to verify that Item_Quantity_Available is equal to 0, like in the previous example. Otherwise, If you just wants to verify if there is data, the condition could be something like that:
if (!rdr.Read())
{
MessageBox.Show("Out of Stock");
}
The third improvemente is to join tables with the join clause.
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
I have the following code . I can extract all data from all data existing in sheets in a workbook and the name of the sheet
foreach (var sheetName in GetExcelSheetNames(connectionString))
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
var dataTable = new DataTable();
string query = string.Format("SELECT {0} as sheetName, * FROM [{0}]", sheetName);
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(dataTable);
ds.Tables.Add(dataTable);
}
}
Then I write the following code to store data in a table in sql server
if (ds.Tables.Count > 0)
{
foreach (DataTable dt in ds.Tables)
{
using (SqlConnection con = new SqlConnection(consString))
{
con.Open();
for (int i = 2; i < dt.Rows.Count; i++)
{
for (int j = 1; j < dt.Columns.Count; j += 3)
{
//Here the problem
SqlCommand command = new SqlCommand( what should I write? ) ;
command.ExecuteNonQuery();
}
}
con.Close();
}
}
My problem is how to store sheetname in a table [Obj CA]?
I think your
"...VALUES('sheetname" + dt.Rows[0][j].ToString() + "' )
should be
"...VALUES('sheetname', '" + dt.Rows[0][j].ToString() + "' )
since you try to insert two values but you didn't seperate them with a comma.
But as a better way, use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
var command = new SqlCommand(#"INSERT INTO [Obj CA] (sheetname, [Rayon])
VALUES('sheetname', #rayon"), con);
for (int i = 2; i < dt.Rows.Count; i++)
{
for (int j = 1; j < dt.Columns.Count; j += 3)
{
command.Parameters.Clear();
command.Parameters.AddWithValue("#rayon", dt.Rows[0][j].ToString());
command.ExecuteNonQuery();
}
}
By the way, since I didn't know your column types, I used AddWithValue as an example but you don't. This method may generate unexpected results sometimes. Use Add overload to specify your parameter type and it's size.
Also I strongly suspect you should change your column definition order as well like (sheetname, [Rayon]) in your INSERT statement.
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);
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.