I have a dataset which contains two tables. Table[0] gets filled with multiple rows. I then need to iterate those rows and for each row run another query and fill those results to Table[1]. What is the correct way to fill a dataset with multiple rows within a loop? Abbreviated code sample of where I am:
DataSet ds = new DataSet();
sql = myquery1;
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
da.Fill(ds, "Products");
foreach (DataRow dr in ds.Tables[0].Rows)
{
productID = ds.Tables[0].Rows[0]["ProductID"].ToString();
if (productID != String.Empty)
{
sql = String.Empty;
sql = myquery2 where productID = 'xxxxx'
da = new SqlDataAdapter(sql, conn);
da.Fill(ds, "ProductProperties");
}
}
This fills the "ProductProperties" datatable on the first loop but doesn't add future results. What's the right way to keep adding multiple result sets to the datatable?
You're going about this the wrong way. You only need one query to populate the child table. E.g.
Dim ds As New DataSet
Using connection As New SqlConnection("connection string here"),
parentAdapter As New SqlDataAdapter("SELECT * FROM ParentTable",
connection),
childAdapter As New SqlDataAdapter("SELECT * FROM ChildTable WHERE ParentID IN (SELECT ParentID FROM ParentTable)",
connection)
connection.Open()
parentAdapter.Fill(ds, "Parent")
parentAdapter.Fill(ds, "Child")
End Using
All you need to do is duplicate the parent query as the subquery for the child table. You can even put both queries inside one data adapter if you want. The point is that there's no need to loop through the parent records and execute a separate query for each one.
You query should return two record sets
SELECT ProductId, Name
FROM Products
SELECT ProductId, Property1, Property2
FROM ProductProperties
Then you can read the data from the above query to a DataSet as follows. So you will get two tables in the DataSet with the results from the two records sets from the above query
using (SqlConnection con = new System.Data.SqlClient.SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "query";
cmd.Connection = con;
con.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
con.Close();
}
}
Related
I currently accessing a database using multiple queries and storing the results from the queries into DatatTables. I decided since I'm using multiple DataTables to store them inside a DataSet.
I can see that data is inside the DataTables when I print them out. However when I try to access them from the DataSet to print out the data, I get nothing back; it is empty.
string querytest1 = "SELECT * FROM test1";
string querytest2 = "SELECT * FROM test2";
string querytest3 = "SELECT * FROM test3";
using(OleDbConnection connection = new OleDbConnection(connectionString)){
OleDbCommand commandtest1 = new OleDbCommand(querytest1 , connection);
OleDbCommand commandtest2 = new OleDbCommand(querytest2 , connection);
OleDbCommand commandtest3 = new OleDbCommand(querytest3 , connection);
connection.Open();
DataSet dataSet = new DataSet();
OleDbDataAdapter dataAdaptertest1 = new OleDbDataAdapter(commandResults);
OleDbDataAdapter dataAdaptertest2 = new OleDbDataAdapter(commandResults);
OleDbDataAdapter dataAdaptertest3 = new OleDbDataAdapter(commandProjects);
DataTable dataTabletest1 = new DataTable();
DataTable dataTabletest2 = new DataTable();
DataTable dataTabletest3 = new DataTable();
dataAdaptertest1.Fill(dataTabletest1 );
dataAdaptertest2.Fill(dataTabletest2 );
dataAdaptertest3.Fill(dataTabletest3 );
dataTabletest1 = dataSet.Tables.Add("test1 ");
dataTabletest2 = dataSet.Tables.Add("test2 ");
dataTabletest3 = dataSet.Tables.Add("test3 ");
Console.WriteLine("DataSet has {0} DataTables \n", dataSet.Tables.Count);
foreach (DataTable objDt in dataSet.Tables)
Console.WriteLine("{0}", objDt.TableName);
return dataSet;
Expected behaviour: is to be able to access a DataTable from the DataSet and print out the data.
Example: Print out the contents in Test1
The code is redundant. I just don't know a better way to do this.
You don't need three adapters to fill a DataSet with the results from three commands.
You can simply write:
string query1 = "SELECT * FROM test1";
string query2 = "SELECT * FROM test2";
string query3 = "SELECT * FROM test3";
DataSet dataSet = new DataSet();
using(OleDbConnection connection = new OleDbConnection(connectionString)){
connection.Open();
OleDbCommand cmd = new OleDbCommand(q1, connection);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(ds, "Test1");
cmd.CommandText = q2;
da = new OleDbDataAdapter(cmd);
da.Fill(ds, "Test2");
cmd.CommandText = q3;
da = new OleDbDataAdapter(cmd);
da.Fill(ds, "Test3");
}
Console.WriteLine("DataSet has {0} DataTables \n", ds.Tables.Count);
foreach (DataTable objDt in ds.Tables)
Console.WriteLine("{0}", objDt.TableName);
The trick is filling the same DataSet three times instead of three different DataTables and giving at each fill a different name for each table created.
But, don't you see that dataSet.Tables.Add() call actually creates new DataTable instance, and trying to set its TableName property to "test1 " (btw. take care, space is not allowed in TableName).
That newly created instance(s) are set to properties dataTabletest1...3 - so, you lose access to the original ones, initially populated with data from the database.
You should do something like this:
DataTable dataTabletest1 = dataSet.Tables.Add("Test1");
DataTable dataTabletest2 = dataSet.Tables.Add("Test2");
DataTable dataTabletest3 = dataSet.Tables.Add("Test3");
dataAdaptertest1.Fill(dataTabletest1);
dataAdaptertest2.Fill(dataTabletest2);
dataAdaptertest3.Fill(dataTabletest3);
Please, check: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/adding-a-datatable-to-a-dataset
I have two tables, one is created by myself and the other is not.
I need to show some columns from both tables in one DatGridView.
Is it possible? If so how can I do it?
If you need anything about my code or database feel free to ask, I'll provide it to you, if I can.
You need to join two tables and fetch the results as below:
I am using my table with MySQL:
using(MySqlConnection connection = new MySqlConnection(MyConnectionString))
using(MySqlCommand cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText = "SELECT pb.Id, pb.Name, pb.MobileNo, e.email FROM phonebook pb INNER JOIN email e ON e.Id= pb.Id";
MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
DataSet ds = new DataSet();
adap.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
How do I show a selected date data from a SQL Server database in a DataGridView?
I tried but that shows all data from database.
Here is the code which triggers when I click the button to show
SqlDataAdapter da = new SqlDataAdapter("select currDate,WtrNm,Type,No from WtrTblAllot", con);
DataSet ds = new DataSet();
da.Fill(ds);
dgvWtrAllot.DataSource = ds.Tables[0];
Since you don't have a WHERE clause in your query its very obvious that it will fetch all data from the database.
SqlDataAdapter da = new SqlDataAdapter("select currDate,WtrNm,Type,No
from WtrTblAllot", con);
Add WHERE clause to your query if you want to fetch only specific records form the database table.
Use your selected date in WHERE clause as #Coder says...
Date selectedDate = Date.Now;
String query = "SELECT currDate,WtrNm,Type,No FROM WtrTblAllot WHERE currDate = #SelectedDate";
SqlComman command = New SqlCommand(query, con);
command.Parameters.AddWithValue("#SelectedDate", selectedDate);
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet ds = new DataSet();
da.Fill(ds);
dgvWtrAllot.DataSource = ds.Tables[0];
When adding some values inside of query, then better practice is using of parameters...
I searched some posts but still cant get it work.
I have a window application written in C#, Here I bind the datagridview to my database:
public static DataSet GetDataSet(string sql)
{
using (SqlConnection cn = new SqlConnection(constr))
{
SqlDataAdapter da = new SqlDataAdapter(sql, cn);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}
and I bind the datagridview in another class:
string sql = "select Amount, Price, Description from myTable";
ds = DbHelper.GetDataSet(sql);
dataGridView2.DataSource = ds.Tables[0];
I created a button for user to update the database after they edit the datagridview:
string sql = "select Amount, Price, Description from myTable";
DbHelper.UpdateDataSet(sql, ds);
MessageBox.Show("done");
public static void UpdateDataSet(string sql, DataSet ds)
{
using (SqlConnection cn = new SqlConnection(constr))
{
SqlDataAdapter da = new SqlDataAdapter(sql, cn);
da.Update(ds);
}
}
Here is the error, occurs at the line da.Update(ds);:
Update requires a valid UpdateCommand when passed DataRow collection with modified rows.
Thanks for help.
EDIT
I can get it work with this:
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(da);
da.UpdateCommand = commandBuilder.GetUpdateCommand();
But only when I show the key in the datagridview as well, otherwise:
Dynamic SQL generation for the UpdateCommand is not supported against a SelectCommand that does not return any key column information.
How to overcome this if I dont want to show the key in datagridview?
SqlCommandBuilder needs the Primary Key to update the field. You can still load the key to the DataGridView, but hide the column.
my command is something like this:
string command = "SELECT * FROM [SheetName1$]; SELECT * FROM [SheetName2$]; ...."
When I do
DataSet set = new DataSet();
using(OleDbDataAdapter adapter = new OleDbDataAdapter(command, connection))
{
adapter.Fill(ds)
}
I end up with an empty DataSet (more specifically I end up with an exception that says Characters found after end of SQL statement). However, if I use only one SELECT query this works fine.
Excel cannot execute more than in one statement. Try making this in two commands.
DataSet set1 = new DataSet();
using(OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [SheetName1$];", connection))
{
adapter.Fill(set1 );
}
DataSet set2 = new DataSet();
using(OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [SheetName2$];", connection))
{
adapter.Fill(set2);
}
Instead of filling in DataSets, fill DataTables and then add said DataTables to a DataSet.
DataSet ds = new DataSet();
DataTable dt1 = ds.Tables.Add("set1");
using(OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [SheetName1$];", connection))
{
adapter.Fill(dt1);
}
DataTable dt2 = ds.Tables.Add("set2");
using(OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [SheetName2$];", connection))
{
adapter.Fill(dt2);
}
can try this in SQL query:
SELECT * FROM [SheetName1$]
UNION ALL
SELECT * FROM [SheetName2$]
I hope this would help