Datagridview with two datasources - c#

I have two tables one is them main table contains (id, Date, TestID, Result)
and the orther is a lookup table (TestID, TestName)
I want to show data like this in datagridview:
Id , Date, Test 1, Test 2, Test 3, Result.
and to be able to save it, is this possible? and how to start

Perhaps you could combine the data from each of your datasources into a single dataset and then assign that dataset as the source of your dataview. However, without further info it's hard to speculate on possible solutions.
However ..
You can combine your resultsets into one DataTable using two SqlDataAdapter to fill the DataTable from the two databases respectively. Here is an example.
DataTable dt = new DataTable();
using(SqlDataAdapter a1 = new SqlDataAdapter("SELECT * FROM [user1]", "Data Source=DBServer1;Initial Catalog=Database1;User ID=user;Password=***"))
a1.Fill(dt);
using(SqlDataAdapter a2 = new SqlDataAdapter("SELECT * FROM [user2]", "Data Source=DBServer2;Initial Catalog=Database2;User ID=user;Password=***"))
a2.Fill(dt);
***ABOVE IS JUST EXAMPLE its not the 100% correct method to do it starting with the connection to the Database , but its something for you to start and think about it ****
a1.Fill(dt) will initialize the DataTable and fill it. a2.Fill(dt) just adds rows to the DataTable dt from the other resultset. This example assumes that the two data sources have the same schema. If not, you have to prepare the datatable to accomodate both resultsets.
Hope this helps.

Certainly, the relationship between the records of first table by the second table need to a shared columns. For example, tables have ID column and it's shared between table one and two, so best way is JOIN tables on two DataTables or Merge by DataTable.Merge Method on .NET.
Other way is, Concatenates two sequences by Enumerable.Concat Method
References:
How to: Concatenate Two Sequences (LINQ to SQL)
DataTable.Merge Method (DataTable)

Related

Create Strongly Typed Dataset for a stored procedure that return more than one table

I have a stored procedure that performs 3 select. How do I create a strongly typed dataset that can access all the 3 tables and read the data. Visual studio by default generates a dataset with the 1st table only
I have already tried using visual studio Typed Dataset, to drag and drop the Stored Procedure.
Stored procedure is something like this:
Create Procedure GetData
As
Begin
Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
End
If you're desperate to do this I don't think you'll succeed with a pure strongly-typed designer generated solution; tableadapters are intended to mediate between a local datatable representation of the db data (your strongly typed datatable) and a database query that returns rows. The "table" in tableadapter related to th datatable, not the database table.
A single tableadapter is not intended to function as a mediator between 3 local datatables and a remote procedure that delivers the output of 3 database queries. Primarily it cannot do this because there is nothing the client side code can use to identify, for your sql of...
Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
...that the results from select * from TableA are supposed to go in TableADataTable in your dataset etc. The fact that the data came out of tableA is lost in the transmission over the wire because it is completely irrelevant and might not even be true.
When a tableadapter is correctly used with a single select, it knows implicitly the datatable the results should be put in. TableADataTable has a corresponding TableATableAdapter, and TableATableAdapter selects data from somewhere in the db and stashes it in the TableADataTable - there is no other table in the dataset that TableATableAdapter is designed to manipulate so it doesn't need any hints about where the block of data goes after it runs the query. TableATableAdapter can even be loaded with a query that doesn't return any data from the database TableA at all; so long as the query it runs produces a set of columns of th right number and type, that data will go in TableADataTable because that's what TableATableAdapter is hardcoded to do. It serves no other datatable, and has no interest in any other datatable.
Because your stored procedure has no way of indicating to the tableadapter which of the result sets should be stored in which table, the solution you're envisaging cannot work.
The simple rule is: "one dog, one done" - "one db query result set, one tableadapter, one strongly typed datatable"
As such, i firmly recommend you use these things as they were intended:
Create 3 tableadapters and corresponding datatables for TableA, TableB and TableC
Fill each independently in your code:
var ds = new StronglyTypedDataSet();
var ata as new TableATableAdapter();
ata.Fill(ds);
var bta as new TableBTableAdapter();
bta.Fill(ds);
var cta as new TableCTableAdapter();
cta.Fill(ds);
"We would like to avoid multiple db calls for a single page" doesn't really make sense - it sounds like a solution to a problem you've imagined rather than on that will really happen. There's so little performance advantage to be gained by trying to execute these things in one hit rather than 3. You might disagree, but test it - don't just go off a hunch. Connections are pooled, statements are cached and prepared, 3 statements could be executed concurrently if you really think it will help vastly.
At the end of the day if you have 9 megabytes of data to pull out of a database, the difference in doing it as 3 pulls of 3 mb each versus 1 pull of 9 is going to be miniscule; you aren't waiting 30 seconds for a connection to open, reading 3 mb in a second, waiting another 30s to close it ad having to do it all over again (total time 183 seconds) and having all the bottleneck attributable to the connection management. Even if you did have a super latency connection that will take 30s to transmit the SELECT and another 30s to start reading data, you can launch your 3 requests simultaneously and by definition it will take the same time to send the 3 SELECTs as it will to invoke 1 procedure call (both take 61 seconds)
If you cannot agree that the reason for trying to do it all in one is spurious then you may wish to keep trying to do it via your chosen method, in which case I think you're going to have to choose:
Use a standard dataadapter and dataset
and then move the data into the typed set to work with it
SqlConnection con = new SqlConnection("YourConnection String");
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand("storedprocedure", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#p1", whatever); //if you have parameters.
SqlDataAdapter da= new SqlDataAdapter(cmd);
da.Fill(ds);
con.Close();
Now you have a dataset with 3 tables in it, it's your problem to figure out which table is which. Let's assume ds.Tables[0] is for TableA:
foreach(var ro in ds.Tables[0].Rows)
typedDs.TableA.AddTableARow(ro.ItemArray);
Repeat it for b and c tables
Convert your 3 queries to 1
Your example seems to indicate all 3 of your tables have the same number of columns. If the columns are the same type too, then you can union the queries, and load them into a single table adapter and fill them into a single strongly typed datatable. You might then have some more work to do splitting them out into separate datatables. Perhaps modify th query to return a column so you can track where the data came from:
Select 'tableA' as wherefrom, ColA, ColB, ColC from TableA
UNION ALL
Select 'tableB' as wherefrom, ColD, ColE, ColF from TableB
UNION ALL
Select 'tableC' as wherefrom, ColG, ColH, ColI from TableC
It's a mess, a hassle, a hack
Why is this so hard? Well.. to quote another old saying: if it's hard, you're doing it wrong. TableAdapters were designed X way and you're trying to use them Y way. Take a step back and examine the reasons behind why you're doing it - that's where the real problem lies

Filter a dataset or datatable .net 2.0

I have to fix something in a .net 2 application and I need to filter a dataset or datatable.
Basically an xml file is read into a dataset and there are inner tables of some parts of the xml with the same name.
EG Customer has table called order and Employee has table called order
now given that this xml is now a dataset how do i filter based on child relationship or
"give all the orders that belong to the customer table"
many thanks
You can use a Dataview for this purpose. Considering the fact that Order table has column named Ordered_Entity (for example) which defines the specific entity made the order then you can do like
DataView dv = new DataView(YourOrderTable);
dv.RowFilter = "Ordered_Entity = 'customer'";

How to merge 2 datatables into one with same number of rows as 1st datatable

Is it possible to merge or Union 2 datatables into 1 with same number of rows as first datatable.
This is using c# and asp.net
Dataset ds = new Dataset(); //Ds has 2 tables with same number of rows.
DataTable dtAll = new DataTable();
dtAll = ds.Tables[0].Copy();
dtAll.Merge(ds.Tables[1], true);
For example: Sl.no Date Amount Sold in first datable
Amount Collected in Datatable 2
The final Datatable should be sl.no Date AmountSold AmountCollected with union.
The Amount SOld and Collected is from the same day.. I hope i am clear.
When i use the above Merge(), it merges into double the rows. What am i missing?!
Thank you!!
Seems what you want to do is JOIN the two tables into one and bring the results, for this you need a Foreign Key of some sort, a unique column that will allow reference both tables (in your case im assuming 'SI.No'
try this SQL statement when you create the Dataset()
SELECT a.*, b.AmountCollected from [table1] a
INNER JOIN [table2] b INTO a.Sino=b.sino 'or whatever column name has the same value as [table1]
that should get you the result you are looking for unless IM not comprehending correctly what you are looking for

How can I select what columns come in from a DataSet into a DataTable?

Being new to working with Data, I hope I'm asking this properly. How can I select what columns come in from a DataSet into a DataTable? I know I can fill a DataTable by using...
DataTable table = dataSet1.Tables[0];
but this brings in all the columns. How can I fill a DataTable with only certain columns?
I'm using .NET 3.5, C#, and a SQL CE 3.5 single table database.
Thanks.
The DataTable is actually filled via a DataAdapter when the DataSet is created. Once you run your query, the columns in the DataTable are set. But, you can use a DataView to apply an additional filter and a column reduction to a DataTable, but the cost of querying the database and pulling data has already occurred, so you should consider making sure your query doesn't pull back more than you need. MSDN is a great resource.
Of course if you're just now learning this, it bears mentioning that while ADO.NET is important to know foundationally, you should be aware that there's a lot of momentum away from raw ADO.NET lately towards things like Entity Framework. While SQL will never die, nor should it, you're going to have to write a whole lot more plumbing code when using ADO.NET then you would with a nice ORM. Check out these posts for more info.
// Assumes that connection is a valid SqlConnection object.
string queryString = "SELECT CustomerID, CompanyName FROM dbo.Customers";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);
DataSet customers = new DataSet();
adapter.Fill(customers, "Customers");
DataTable table = customers.Tables[0];
Instead of "CustomerID, CompanyName" you can put the columns you want to select.
For further learning check this MSDN link.

Reading DataSet

How do I read data from a DataSet in WPF? I have a train schedule table with just 2 columns and I want to be able to read the departure times and calculate when the next train is leaving. For example, the time now is 12:29 and my application should tell me that next train will depart at 12:33.
I already googled left and right. I'm on .NET 3.5.
DataSet resembles database. DataTable resembles database table, and DataRow resembles a record in a table. If you want to add filtering or sorting options, you then do so with a DataView object, and convert it back to a separate DataTable object.
If you're using database to store your data, then you first load a database table to a DataSet object in memory. You can load multiple database tables to one DataSet, and select specific table to read from the DataSet through DataTable object. Subsequently, you read a specific row of data from your DataTable through DataRow. Following codes demonstrate the steps:
SqlCeDataAdapter da = new SqlCeDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
da.SelectCommand = new SqlCommand(#"SELECT * FROM FooTable", connString);
da.Fill(ds, "FooTable");
dt = ds.Tables["FooTable"];
foreach (DataRow dr in dt.Rows)
{
MessageBox.Show(dr["Column1"].ToString());
}
To read a specific cell in a row:
int rowNum // row number
string columnName = "DepartureTime"; // database table column name
dt.Rows[rowNum][columnName].ToString();
If ds is the DataSet, you can access the CustomerID column of the first row in the first table with something like:
DataRow dr = ds.Tables[0].Rows[0];
Console.WriteLine(dr["CustomerID"]);
If this is from a SQL Server datebase you could issue this kind of query...
Select Top 1 DepartureTime From TrainSchedule where DepartureTime >
GetUTCDate()
Order By DepartureTime ASC
GetDate() could also be used, not sure how dates are being stored.
I am not sure how the data is being stored and/or read.
TL;DR: - grab the datatable from the dataset and read from the rows property.
DataSet ds = new DataSet();
DataTable dt = new DataTable();
DataColumn col = new DataColumn("Id", typeof(int));
dt.Columns.Add(col);
dt.Rows.Add(new object[] { 1 });
ds.Tables.Add(dt);
var row = ds.Tables[0].Rows[0];
//access the ID column.
var id = (int) row.ItemArray[0];
A DataSet is a copy of data accessed from a database, but doesn't even require a database to use at all. It is preferred, though.
Note that if you are creating a new application, consider using an ORM, such as the Entity Framework or NHibernate, since DataSets are no longer preferred; however, they are still supported and as far as I can tell, are not going away any time soon.
If you are reading from standard dataset, then #KMC's answer is what you're looking for. The proper way to do this, though, is to create a Strongly-Typed DataSet and use that so you can take advantage of Intellisense. Assuming you are not using the Entity Framework, proceed.
If you don't already have a dedicated space for your data access layer, such as a project or an App_Data folder, I suggest you create one now. Otherwise, proceed as follows under your data project folder:
Add > Add New Item > DataSet. The file created will have an .xsd extension.
You'll then need to create a DataTable. Create a DataTable (click on the file, then right click on the design window - the file has an .xsd extension - and click Add > DataTable). Create some columns (Right click on the datatable you just created > Add > Column). Finally, you'll need a table adapter to access the data. You'll need to setup a connection to your database to access data referenced in the dataset.
After you are done, after successfully referencing the DataSet in your project (using statement), you can access the DataSet with intellisense. This makes it so much easier than untyped datasets.
When possible, use Strongly-Typed DataSets instead of untyped ones. Although it is more work to create, it ends up saving you lots of time later with intellisense. You could do something like:
MyStronglyTypedDataSet trainDataSet = new MyStronglyTypedDataSet();
DataAdapterForThisDataSet dataAdapter = new DataAdapterForThisDataSet();
//code to fill the dataset
//omitted - you'll have to either use the wizard to create data fill/retrieval
//methods or you'll use your own custom classes to fill the dataset.
if(trainDataSet.NextTrainDepartureTime > CurrentTime){
trainDataSet.QueueNextTrain = true; //assumes QueueNextTrain is in your Strongly-Typed dataset
}
else
//do some other work
The above example assumes that your Strongly-Typed DataSet has a column of type DateTime named NextTrainDepartureTime. Hope that helps!

Categories