GridView Table 1 related to Table 2 - c#

Sorry I know Title is really confusing but I couldn't figure out what exactly to put down.
Basically I created a Grid View which queries database and displays data. It works perfectly, no complain, however what I have right now is,
but what I want is,
Question: I am not sure how can I do this, can someone just point me out in right direction please ?
I think I will going to use nested gridviews.

Try to change your SELECT Query like below... It will you to get the Expected Result...
SQL Fiddle : http://www.sqlfiddle.com/#!3/00b5f/15
I have named the Table as Fruits
SELECT CrateTitle,CrateDescription,CrateID,
stuff(
(
SELECT ','+ [FruitTitle] FROM fruits WHERE CrateID = t.CrateID FOR XML path('')
),1,1,'') Types_of_Fruits_in_Crate
FROM (SELECT DISTINCT CrateTitle,CrateDescription,CrateID FROM fruits )t
OR
CREATE a PROC
*Place this Query in that Proc*
*Call that Proc*
*assign that Result set to GridView*
You can Assign he Stored Proc Result set to GridView by using the Below Code :
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection("Your Connection String");
try
{
connection.Open();
string spName = "YOURStoredProcudureName";
SqlCommand sqlCmd = new SqlCommand(spName, connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlDa.Fill(dt);
if (dt.Rows.Count > 0)
{
//display the DataTable to a Data control like GridView for example
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Fetch Error:";
msg += ex.Message;
throw new Exception(msg);
}
finally
{
connection.Close();
}

This is more an sql (or whatever langue your database engine uses) problem than a c# problem although one solution from c# would be (though it may be a bit of extra work) to use a html literal to draw you table at run time
the other option would be to change your sql but without more information i can't say if you could perhaps use a group by on changeID or a pivot table

Related

How do I filter a datagridview with text?

I'm making an application where we can see data from my database in a datagridview. I got to a point that I need to filter somethings and I'm only able to filter with "numbers" for example (IdProducts), this is the code I'm using:
string query= "SELECT * FROM alunos where Estado="+textBox1.Text;
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
in this code I'm trying to filter the column "Estado" which is text and it gives me this error,
Unknown column 'A' in 'where clause'
"A" is what I'm trying to filter (is a camp from Estado column)
My question is how can I be able to filter with not only numbers but text too?
string query= "SELECT * FROM alunos where Estado="+textBox1.Text;
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
Yuo need to change your code to use a parameterized query like this
string query= "SELECT * FROM alunos where Estado=#state";
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
cmd.Parameters.Add("#state", MySqlDbType.VarChar).Value = textBox1.Text;
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
The problem in your original code is caused by the fact that you concatenate the string value from the textbox without adding quotes around it. In this way the parser is fooled and thinks that you are naming a field and, of course, cannot find it.
However, "resolving" the problem simply adding single quotes around the textbox is not a real solution because you are opening your code to Sql Injection attacks. Instead, if you use a parameterized queries, you don't have your original problem, you avoid sql injection, you will not face other 'syntax errors' caused by the presence of single quotes in your textbox.text property and your database engine can optimize the query because parsing it just one time even if you call it more than one time.

Changing date in drop down list to yyyy/mm/dd in c#

I currently have a Drop down list that has been bound with dates from a database. The dates differ depending on which username is selected in a different drop down list. I am trying to populate a GridView depending on these values and when the selected index changes on the dates drop down list.
However the dates being displayed in my drop down list are dd/mm/yyyy 00:00:00, which means that I can't use them to display data from the database based on the values. As my Date in the database are stored as yyyy/mm/dd. As I am getting the error : 'Conversion failed when converting date and/or time from character string.'
Any idea on how to change the format in the drop down list?
I understand that this might be used: DateTime.ToString("yyyy-MM-dd"); however I can't work out where.
C# for binding data to my second drop down list:
private void BindDropDownList2(String field)
{
DataTable dataTable = new DataTable();
SqlConnection con = new SqlConnection(#"Data Source=(local)\;Initial Catalog=SmallBatch;Integrated Security=True;");
try
{
con.Open();
String Query = "Select StockDate from Stock_Take WHERE Username = #Value1";
SqlCommand sqlCmd = new SqlCommand(Query, con);
sqlCmd.Parameters.AddWithValue("#Value1", field);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlDa.Fill(dataTable);
if (dataTable.Rows.Count > 0)
{
DropDownList2.DataSource = dataTable;
DropDownList2.DataTextField = "StockDate";
DropDownList2.DataValueField = "StockDate";
DropDownList2.DataBind();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Fetch Error";
msg += ex.Message;
throw new Exception(msg);
}
finally
{
con.Close();
}
}
Firstly , a DataTable is unnecessary here.Go with a IDataReader , it's a better option.The reason is simple.A DataTable uses a DataAdapter and stores data from the database.Which means you have 2 datatables,one in the database(original one) and one in the code behind.If you go with IDataReader it means that you are reading the data-table from the database itself and not storing it again in code-behind.
Ow, did i forget to tell that a DataReader is proven to be faster than a DataAdapter ? :).
I'l glad that you almost answered you own question with this line :
I understand that this might be used: DateTime.ToString("yyyy-MM-dd")
All you have to do is put it all together :
SqlCommand sqlCmd = new SqlCommand(Query, con);
sqlCmd.Parameters.AddWithValue("#Value1", field);
SqlDataReader dr = sqlCmd.ExecuteReader();
While (dr.Read())
{
DropDownList1.Items.Add(new ListItem(dr[0].ToString("yyyy MMM ddd"), ""));
} //I didn't debug this line but it should work :)
Update
As OP said that the data-type of the given column is VarChar, then .ToString() will do it :)
DropDownList1.Items.Add(new ListItem(dr[0].ToString()),"");

Update DataGrid after insert with procedure

I know this question was asked but I can't figure out why this action is so complex.
So I have a Produs table
SELECT TOP 1000 [IDProdus]
,[Denumire]
,[UM]
,[Pret]
,[IDFurnizor]
,[IDCategorie]
,[IDTipProdus]
,[OperatorAdaugare]
,[DataAdaugare]
,[OperatorModificare]
,[DataModificare]
FROM [Proiect].[dbo].[Produse]
This is my table's columns. I added via Data Sources GUI from Visual Studio a DataSet with the content of this table (no actual code wrote by me).
Now I have a procedure that will insert me a new row in this Table.
Here is the code:
private void dToolStripMenuItem_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("connection-string-here");
string Query = "spGE_getProduse_Edit"; // Stored procedure name.
int Integer;
conn.Open();
// Creating SqlCommand object
SqlCommand com = new SqlCommand(Query, conn );
// Here we declaring command type as stored procedure:
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#IDProdus", 0);
com.Parameters.AddWithValue("#Denumire ",
denumireTextBox.Text.ToString());
com.Parameters.AddWithValue("#UM ",
uMTextBox.Text.ToString());
com.Parameters.AddWithValue("#Pret ",
Double.Parse(pretTextBox.Text));
com.Parameters.AddWithValue("#IDFurnizor ",
Int16.Parse(iDFurnizorTextBox.Text));
com.Parameters.AddWithValue("#IDCategorie ",
Int16.Parse(iDCategorieCombobox.SelectedValue.ToString()));
com.Parameters.AddWithValue("#IDTipProdus ",
Int16.Parse(iDTipProdusCombobox.SelectedValue.ToString()));
com.Parameters.Add("#IDProdusScris", SqlDbType.BigInt);
com.Parameters["#IDProdusScris"].Direction =
ParameterDirection.Output;
com.ExecuteNonQuery();
conn.Close();
Integer =
Int32.Parse(com.Parameters["#IDProdusScris"].Value.ToString());
}
Now after insert I want to update myGrid with the new record. I tried
dataGridView1.Refresh(); and dataGridView1.Update();, with no result.
Is there a way to update the grid? It looks like a simple task for VS, but I couldn't find a simple solution.
What I saw only and read on MSDN looked like some very complex operations just for a simple refresh. (It was about getting the state of the row and insert the row if the state was Added).
So is there any simple way to do this, or I have to write a method that will refresh my dataGridView every time I want (I mean to re-query my table and rebuild the dataSource)
Try like this:
dataGridView1.Refresh(); and dataGridView1.Update(); will not fetch updated records from db.
Source
You can use stored procedures are pre-complied
Create Procedure Sp_getProducts
as
BEGIN
SELECT TOP 1000 [IDProdus]
,[Denumire]
,[UM]
,[Pret]
,[IDFurnizor]
,[IDCategorie]
,[IDTipProdus]
,[OperatorAdaugare]
,[DataAdaugare]
,[OperatorModificare]
,[DataModificare]
FROM [Proiect].[dbo].[Produse]
END
Use this code which Uses Using Statements
using (SqlConnection conn = new SqlConnection("connection-string-here"))
{
conn.Open();
using(SqlCommand cmd=new SqlCommand("Sp_getProducts",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable ds = new DataTable();
da.Fill(ds);
gridView.DataSource = ds;
gridView.DataBind();
conn.Close();
}
}
Try resetting your datasource:
dataGridView1.DataSourcce = null;
dataGridView1.DataSource = [YOUR DATASET];
dataGridView1.Refresh();
dataGridView1.Update();

Insert data into Sql Compact

I have Handheld device that connect to Sql Server database, read the Sql server data and get it on the SQL Compact database that is located on device. This is my code:
public void InsertData() // Function insert data into SQL commapct database
{
dt = new DataTable();
dt = SqlServer_GetData_dt("Select id_price, price, id_item from prices", SqlCeConnection); // get data form sql server
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
string sql = "";
sql = "insert into prices" +
" ( id_prices, price,id_item) values('"
+ dt.Rows[i]["id_price"].ToString().Trim() + "', '"
+ dt.Rows[i]["price"].ToString().Trim() + "', '"
+ dt.Rows[i]["id_item"].ToString().Trim() + "')";
obj.SqlCE_WriteData_bit(sql, connection.ConnectionString);//insert into sql compact
}
}
}
public DataTable SqlServer_GetData_dt(string query, string conn)
{
try
{
DataTable dt = new DataTable();
string SqlCeConnection = conn;
SqlConnection sqlConnection = new SqlConnection(SqlCeConnection);
sqlConnection.Open();
{
SqlDataReader darSQLServer;
SqlCommand cmdCESQLServer = new SqlCommand();
cmdCESQLServer.Connection = sqlConnection;
cmdCESQLServer.CommandType = CommandType.Text;
cmdCESQLServer.CommandText = query;
darSQLServer = cmdCESQLServer.ExecuteReader();
dt.Load(darSQLServer);
sqlConnection.Close();
}
return dt;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
DataTable dt = new DataTable();
return dt;
}
}
public object SqlCE_WriteData_bit(string query, string conn)
{
try
{
string SqlCeConnection = conn;
SqlCeConnection sqlConnection = new SqlCeConnection(SqlCeConnection);
if (sqlConnection.State == ConnectionState.Closed)
{
sqlConnection.Open();
}
SqlCeCommand cmdCESQLServer = new SqlCeCommand();
cmdCESQLServer.Connection = sqlConnection;
cmdCESQLServer.CommandType = CommandType.Text;
cmdCESQLServer.CommandText = query;
object i = cmdCESQLServer.ExecuteScalar();
sqlConnection.Close();
return i;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return 0;
}
}
This is all work fine but the problem is that all this work very slow. I have 20 000 row that's need to be inserted into SQL compact database.
Is there any way for faster insert?
Thanks.
Aside from the obvious poor usage of the Connection for every call, you can greatly improve things by also eliminating the query processor altogether. That means don't use SQL. Instead open the destination table with TableDirect and a SqlCeResultset. The iterate through the source data (a DataTable is a bad idea, but that's a completely different thing) and use a series of CreateRecord, SetValues and Insert.
A pretty good example can be found here (though again, I'd use SetValues to set the entire row, not each individual field).
Reuse your connection and don't create a new connection for every INSERT statement.
Instead of passing a connection string to your SqlCE_WriteData_bit method, create the connection once in the InsertData method, and pass the connection object to SqlCE_WriteData_bit.
Put all the data into a DataTable and then use a SqlCeDataAdapter to save all the data with one call to Update. You may have to fiddle with the UpdateBatchSize to get the best performance.
Looking more closely, I see that you already have a DataTable. Looping through it yourself is therefore ludicrous. Just note that, as you have it, the RowState of every DataRow will be Unchanged, so they will not be inserted. I think that you can call DataTable.Load such that all RowState values are left as Added but, if not, then use a SqlDataAdapter instead, set AcceptChangesDuringFill to false and call Fill.
Is there any way for faster insert?
Yes, but it probably won't be "acceptably fast enough" when we're talking about inserting 20k rows.
The problem I can see is that you are opening a connection for every single row you are retrieving from SqlServer_GetData_dt, that is, you open a connection to insert data 20k times...opening a connection is an expensive transaction. You should build the whole query using a StringBuilder object and then execute all the insert statements in one batch.
This will bring some performance gains but don't expect it to solve you're problem, inserting 20k rows will still take some time, specially if indexes need to be re-built. My suggestion is that you should thoroughly analyse your requirements and be a bit smarter about how you approach it. Options are:
bundle a pre-populated database if possible so your app doesn't have to suffer the population process performance penalties
if not, run the insert process in the background and access the data only when the pre-population is finished

Issue with conducting SQL statement within ASP.Net C# code

doubles quotes dont work so you have to type 'some value' to actually do variable comparisons when doing direct execution of SQL statements.
Problem is that now when I execute the SQL statement from ASP.NET code I dont seem to be getting any readings...I am not even getting errors :S....
I HAVE tried executing the SQL statement on its own, and it does work.
public static string testExi(string localIncidentNum)
{
try
{
string query = "SELECT TOP 1 UniqueColID From DBNAME WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC";
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection(connectionStr);
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
connection.Open();
SqlDataAdapter adp = new SqlDataAdapter(command);
adp.Fill(dt);
connection.Close();
command.Dispose();
connection.Dispose();
if (dt.Rows.Count != 0)
{
string UniqueColID = dt.Rows[0]["UniqueColID"].ToString();
return UniqueColID;
}
else
{
return null;
}
string some = dt.Rows[0]["UniqueColID"].ToString();
return some;
}
catch (Exception err)
{
Global.tmpmsg = " Updating follow up was not successful. " + err.ToString();
return null;
}
}
If I hardcode an incident value in the SELECT statement it works but if I hardcode the incident value in .addwithvalue, it doesn't work.
command.Parameters.AddWithValue("#localIncidentNum", "12-023696");
Double check your sql statement:
SELECT TOP 1 UniqueColID From WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC
From Where?
Edit
In observance of your change, best to always be as accurate as possible when describing your problem. Leaving out something like the table name of a sql statement is very misleading.
Perhaps add a datatype to your command parameter. I believe that you are not getting anything because it may be timing out on the command.
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
command.Parameters[0].SqlDbType = SqlDbType.VarChar;
I found a similar problem here, also using Varchar:
AddWithValue without DBType causing queries to run slowly
I solved it. The problem was that I (for some reason) needed to put the full path of the table before the table name in sql code when executing it from C sharp file:
SELECT TOP 2 [DB name].[dbo]. [table name]

Categories

Resources