I need to compare two datatable and simply check if Datatable(A) contains rows which are in Datatable(B).
Then rows from (B) which will not be in (A) will be inserted into (A). So basically target is to insert rows from (B) into (A) but only those rows which are not already presented.
Both Datables have same structure, same columns and datatypes.
I donĀ“t want to do it with foreach loop for every Datarow(B) and compare with every Datarow in (A) it will be very slow solutions.
Thank you in advance
Related
I have 2 script components which extract data from result set objects say User::AllXData and User::AllYData.
It is run through a foreach loop and the data is stored in a data table.
Next, I'm adding the data into a excel sheet using Excel destination. Now when I do that. All the data corresponding to column A (i.e, the data from User::AllXData) is being added to the excel sheet, but the column B gets filled with null values till the end of column A's data.
Then column B gets filled leaving column A with null data. It's supposed to be aligned.
Is there a workaround for this?
Edit:
After a long of grinding and running many tests, finally came across a solution.
The answer to this is pretty simple. Instead of using two objects as result set, it's better to use only one.
If you're going to query from a single source, include all the required columns in your SQL query into one object result set and use that as a read only variable in the script component.
Create a single data table that includes all the required columns and adds them into your excel destination row by row without any null values.
Here's an article that has a good example.
I have a datatable with almost 20 columns in it. in another DT i get only the columns I want. Recently my requirements have changed i.e. Firstly the number of columns in the original DT were constant but now it increases or decreases depending upon the data.
So now, if I statically provide the column names I need in my new DT it isnt of much use to me.
Is there any way in which I can include those columns which may or may not be in the Original Datatable????
For eg: col1|col2|col3|.......col20.
The columns that may bve present or absent fall between col12 and col 16. Is there anyway in which I could make it work????
EDIT:
I want col1,col2,col3 and all columns aftr col12...can I do it???
You can have total number of columns from datatable using
DataTable.Columns.Count
So you will know how many columns are there and you will know which column is in datatable and which is not.
When I add rows to a Datatable, and later iterate that Datatable.
Will I get the rows in the same order then they were inserted? First in, first out?
Or can I not rely on that order?
row = datatable.NewRow();
row("id") = 1;
table.Rows.Add(row);
row = datatable.NewRow();
row("id") = 2;
table.Rows.Add(row);
foreach(Row row in datatable.AsEnumerable())
{
// FIFO here? always get row with id 1 as first row and row with id 2 as second row?
}
If you do this manually, YES of course.
MSDN - Adding Data to a DataTable
Note that values in the array are matched sequentially to the columns,
based on the order in which they appear in the table.
Yes, normally that is what should happen.
If you need an explicit ordering of the rows I would suggest you sort them before iterating through them. Either by doing an OrderBy<> linq type query or by using the Select method on the DataTable.
Also, you can use the Rows property of the DataTable to get an enumerable of all rows instead of doing the AsEnumerable call.
Edit:
By inspecting the decompiled sources for the DataTable I found that the Rows property of the DataTable returns a DataRowCollection object. The DataRowCollection stores the rows in a binary tree based structure that allows you to fetch the items based on its array index. So it will return the rows in the same order as they were added. As long as we expose an indexer that takes a numerical index this is implied.
In addition, the AsEnumerable extension method, will turn the Rows into an EnumerableRowsCollection that wraps the same types as an IEnumerable<DataRow>.
Am using foreach loop that contain some code to retraive data from database. first time it returns some rows from database.In second looping it returns some rows so and so. My question is may i merge the looping rows to single dataset?.
please help me to merge that row values to single dataset....
As #Tim Schmelter mentioned there is also the Merge() method on datasets. This will allow you to different types of merges, including updates which will stop you having duplicate rows if you have the same row in each dataset. This maybe better than using a for loop to add the rows from one to the other depending on the type of data you have.
you can read more on this here:
http://msdn.microsoft.com/en-us/library/803bh6bc.aspx
This is provided I understood you correctly ...
DataTable tbl = new DataTable();
foreach (DataRow row in data.Rows)
{
tbl.Rows.Add(row);
}
Then just add the DataTable to a DataSet of your choice.
I am writing this in C# using .NET 3.5. I have a System.Data.DataSet object with a single DataTable that uses the following schema:
Id : uint
AddressA: string
AddressB: string
Bytes : uint
When I run my application, let's say the DataTable gets filled with the following:
1 192.168.0.1 192.168.0.10 300
2 192.168.0.1 192.168.0.20 400
3 192.168.0.1 192.168.0.30 300
4 10.152.0.13 167.10.2.187 80
I'd like to be able to query this DataTable where AddressA is unique and the Bytes column is summed together (I'm not sure I'm saying that correctly). In essence, I'd like to get the following result:
1 192.168.0.1 1000
2 10.152.0.13 80
I ultimately want this result in a DataTable that can be bound to a DataGrid, and I need to update/regenerate this result every 5 seconds or so.
How do I do this? DataTable.Select() method? If so, what does the query look like? Is there an alternate/better way to achieve my goal?
EDIT: I do not have a database. I'm simply using an in-memory DataSet to store the data, so a pure SQL solution won't work here. I'm trying to figure out how to do it within the DataSet itself.
For readability (and because I love it) I would try to use LINQ:
var aggregatedAddresses = from DataRow row in dt.Rows
group row by row["AddressA"] into g
select new {
Address = g.Key,
Byte = g.Sum(row => (uint)row["Bytes"])
};
int i = 1;
foreach(var row in aggregatedAddresses)
{
result.Rows.Add(i++, row.Address, row.Byte);
}
If a performace issue is discovered with the LINQ solution I would go with a manual solution summing up the rows in a loop over the original table and inserting them into the result table.
You can also bind the aggregatedAddresses directly to the grid instead of putting it into a DataTable.
most efficient solution would be to do the sum in SQL directly
select AddressA, SUM(bytes) from ... group by AddressA
I agree with Steven as well that doing this on the server side is the best option. If you are using .NET 3.5 though, you don't have to go through what Rune suggests. Rather, use the extension methods for datasets to help query and sum the values.
Then, you can map it easily to an anonymous type which you can set as the data source for your grid (assuming you don't allow edits to this, which I don't see how you can, since you are aggregating the data).
I agree with Steven that the best way to do this is to do it in the database. But if that isn't an option you can try the following:
Make a new datatable and add the columns you need manually using DataTable.Columns.Add(name, datatype)
Step through the first datatables Rows collection and for each row create a new row in your new datatable using DataTable.NewRow()
Copy the values of the columns found in the first table into the new row
Find the matching row in the other data table using Select() and copy out the final value into the new data row
Add the row to your new data table using DataTable.Rows.Add(newRow)
This will give you a new data table containing the combined data from the two tables. It won't be very fast, but unless you have huge amounts of data it will probably be fast enough. But try to avoid doing a LIKE-query in the Select, for that one is slow.
One possible optimization would be possible if both tables contains rows with identical primary keys. You could then sort both tables and step through them fetching both data rows using their array index. This would rid you of the Select call.