Merging 2 datatables in to 1 datatable with same number of rows. - c#

How can i merge two Datatables into the same row. I am using different stored procedures to get data into datasets. In asp.net using c#, i want to merge them so there are same number of rows as table 1 with an added column from table 2.
For example:
DataTable table1 = dsnew.Tables[0];
DataTable table2 = dsSpotsLeft.Tables[0];
table1.Merge(table2);
This is fetching me 4 rows instead of 2 rows. What am i missing here? Thanks in advance!!

You cannot use the method Merge in this case, instead you should create new DataTable dt3, and then add columns and rows based on the table 1 and 2:
var dt3 = new DataTable();
var columns = dt1.Columns.Cast<DataColumn>()
.Concat(dt2.Columns.Cast<DataColumn>());
foreach (var column in columns)
{
dt3.Columns.Add(column.ColumnName, column.DataType);
}
//TODO Check if dt2 has more rows than dt1...
for (int i = 0; i < dt1.Rows.Count; i++)
{
var row = dt3.NewRow();
row.ItemArray = dt1.Rows[i].ItemArray
.Concat(dt2.Rows[i].ItemArray).ToArray();
dt3.Rows.Add(row);
}

Without knowing more about the design of these tables, some of this is speculation.
What it sounds like you want to perform is a JOIN. For example, if you have one table that looks like:
StateId, StateName
and another table that looks like
EmployeeId, EmployeeName, StateId
and you want to end up with a result set that looks like
EmployeeId, EmployeeName, StateId, StateName
You would perform the following query:
SELECT Employee.EmployeeId, Employee.EmployeeName, Employee.StateId, State.StateName
FROM Employee
INNER JOIN State ON Employee.StateId = State.StateId
This gives you a resultset but doesn't update any data. Again, speculating on your dataset, I'm assuming that your version of the Employee table might look like the resultset:
EmployeeId, EmployeeName, StateId, StateName
but with StateName in need of being populated. In this case, you could write the query:
UPDATE Employee
SET Employee.StateName = State.StateName
FROM Employee
INNER JOIN State ON Employee.StateId = State.StateId
Tested in SQL Server.

Assuming you have table Category and Product related by CategoryID, then try this
var joined = from p in prod.AsEnumerable()
join c in categ.AsEnumerable()
on p["categid"] equals c["categid"]
select new
{
ProductName = p["prodname"],
Category = c["name"]
};
var myjoined = joined.ToList();
Sources
LINQ query on a DataTable
Inner join of DataTables in C#
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/ecb6a83d-b9b0-4e64-8107-1ca8757fe58c/
That was a LINQ solution. You can also loop through the first datatable and add columns from the second datatable

Related

C# SqlCommandBuilder , CommandUpdate - how to write correct update based on select with outer join tables

I want is to update 2 fields: p.FlagaWaznosci and p.Notatka
My select looks like:
Select DISTINCT p.id,p.Model_Number,p.Product_Name,p.Website_Link,p.Entry_date,p.LastUpdate_date,p.PrzydzialRozmiarow_ID,p.FlagaWaznosci,p.Notatka,pr.NazwaRozmiarowki,wd.LINK_StockX
from Products p with(nolock)
left outer join Widok_Model_Sklep_Stockx_Linki wd with(nolock) on wd.Product_ID = p.id
left outer join PrzydzialRozmiarow pr with(nolock) on pr.id = p.PrzydzialRozmiarow_ID
inner join Shops s with(nolock) on s.ID = p.Shop_ID
There is just outer joins to get correct data that I need to be displayed in gridview. And now when values p.FlagaWaznosci or p.Notatka is changed I want to save update in my database.
I try to use
//loads dataand fill to gridview
DataTable WszystkieProduktyDlaDanegoSklepu;
SqlDataAdapter sda555123 = new SqlDataAdapter("here is my select", conn123);
sda555123.Fill(WszystkieProduktyDlaDanegoSklepu);
//later update table Prooducts and save changed on p.Notatka and p.FlagaWaznosci
cmdbl = new SqlCommandBuilder(sda555123);
cmdbl.ConflictOption = ConflictOption.OverwriteChanges;
sda555123.Update(WszystkieProduktyDlaDanegoSklepu);
But this way I have error
So I searched a lot and found: I have to write own CommandUpdate.
So ... sda555123.UpdateCommand and I don't have idea how can I write own update for it in update command.
The update in SQL Server should looks like:
Update Products
set FlagaWaznosci = #Flagawaznosci from my sda555123,
Notatka = #Notatka from my sda555123
where id = # p.ID from my sda555123
How my command update should looks like here?
EDIT 1 :
i try added : WszystkieProduktyDlaDanegoSklepu.PrimaryKey = new DataColumn[] { WszystkieProduktyDlaDanegoSklepu.Columns["id"] }
but nothing . Still this error.
I would solve the problem by changing the approach instead of mutating the update command of the SqlDataAdapter.
Given that Products.id in your query is unique within the result set:
1- Create a temporary table (local or global), having its columns same as the result of the query with id as primary key.
2- Insert data into the temporary table using your select statement.
3- DataAdatper.selectQuery.commandText is set to "select * from TempTable"
4- The update command is now based on a simple select statement, consequently any change in the datagridview/datatable can be updated to the temptable using dataadapter.update(datatable)
5- As for the final database update, you could use the below statement
Update Prd
set Prd.FlagaWaznosci = TempTable.FlagaWaznosci ,Prd.Notatka = TempTable.Notatka etc.. all the fields that need to be updated
from my Products as Prd
Inner Join TempTable on TempTable.id = Prd.id
Note that the update in (5) will affect all rows, even unchanged ones.
To address this issue you can proceed as below
1- Save changed ids in a list.
List<string> lst = new List<string>();
foreach(DataRow dr in datatable.GetChanges(DataRowState.Modified))
{
lst.add(dr["id"].ToString());
}
2- Convert your list to a string value to be concatenated with the query in (5)
String strchange = String.Join(",",lst); //will give you id1,id2,...
//The update query becomes
Update Prd
set Prd.FlagaWaznosci = TempTable.FlagaWaznosci ,Prd.Notatka =
TempTable.Notatka etc.. all the fields that need to be updated
from my Products as Prd
Inner Join TempTable on TempTable.id = Prd.id
Where Prd.id In ( strchange )
Kindly update your tables separately because in join you just seen two or more than two tables into one table form . but you cant do any crud operation on

select latest 3 records from sql database

My table name is tblEvent and its columns are EventID, Name, Description, EventTypeID, TotalBudget, CustomerID, EventStatus, EventDate
I want to select the latest 3 records.
I have tried this:
public DataTable HomeEvents()
{
string query = "select TOP 3 tblEvent.*, tblCustomer.Name as 'CustomerName', tblCustomer.Photo AS 'CustomerPhoto' from tblEvent ORDER BY EventID DESC, tblCustomer where tblEvent.CustomerID = tblCustomer.CustomerID";
List<SqlParameter> lstParams = new List<SqlParameter>();
DataTable dt = DBUtility.SelectData(query, lstParams);
return dt;
}
The order by clause should be after the where clause:
select top 3
tblEvent.*,
tblCustomer.Name as 'CustomerName',
tblCustomer.Photo AS 'CustomerPhoto'
from
tblEvent
where
tblEvent.CustomerID = tblCustomer.CustomerID
order by
EventID desc,
tblCustomer
Note: If EventID is auto-incremented (primary key, identity) and the records are actually created in the order that they occured, then the field would be in increasing order over time. Otherwise you would need to use the EventDate field for sorting (as Tareq Alothman suggested).
As Guffa said, Order By comes after where, and you need to
"Order By EventDate DESC"
Change your SQL statement to read
... ORDER DESC BY ...
This will sort in reverse order, the first three are now the last three.

How to bind Gridview when performing union on two database and applying some conditions on it?

I have an table name dbo.EmpInfo having 4 columns
1-UserId 2-SubUserId 3-Year 4-Status
I have an another table (in other database) name dbo.EmpInfo1 having 4 columns
1-UserId 2-SubUserId 3-Year 4-Status
UserId may be repeating in both tables..
Now i have to find those UserId from Both tables whose Status="Success" and this status count is < 10 and bind these values in Gridview..
for ex-I have an UserId say mayank#gmail.com and in dbo.EmpInfo it has status count=5(Status="Success") and in dbo.EmpInfo1 it has status count=7 so from both tables the total count for mayank#gmail.com is 12 so we have to bind this userId in Gridview. and Gridview having all the above columns..
i have a procedure -
ALTER proc [dbo].[sp_countUserDetails]
as
begin try
begin transaction
Select distinct(UserId) from EmpInfo where Status='Success'
union all
Select distinct(UserId) from MyDB.dbo.EmpInfo1 where Status='Sucess'
commit transaction
end try
in my .cs file i used
SqlDataReader dr = ms.sp_SelectExecuter("sp_countUserDetails");
DataTable dt = new DataTable();
dt.Load(dr);
foreach (DataRow DR in dt.Rows)
{
ms = new MethodStore();
ms.sp_SelectExecuter("sp_usercount", "#userid", (DR["UserId"]).ToString());
}
and the Procedure is-
ALTER Procedure [dbo].[sp_usercount]
#userid varchar(50)
as
declare #count1213 dec =0, #count1314 dec =0;
begin try
begin transaction
select #count1314= count(UserId) from EmpInfo where Status='Status' and UserID=#userid;
select #count1213= count(UserId) from MyDB.dbo.EmpInfo1 where Status='Success' and UserID=#userid;
select #count1213+#count1314 as 'Count'
if((#count1213+#count1314)>=10)
insert into MyTaxCafe.dbo.demo values (#userid);
commit transaction
end try
bt the table dbo.demo doesn't contain distinct UserId..because our Procedure
[dbo].[sp_countUserDetails]
give Distinct values from both table but at due to Union there is an redundancy can we control it because Same UserId may be Exist in both tables
First you need a SQL to query two database , you may try it like this
SELECT Status FROM [database1].[dbo].[TableName] AS t1 INNER JOIN [database2].[dbo].[TableName] AS t2
ON (t1.UserId = t2.UserId)
WHERE Status='Success'
GROUP BY Status
Having COUNT(Status) < 10
in your C# code , use SqlDataAdapter to fill DataTable,
then set DataGridView's field DataSource = DataTable
You must use union from your query to get expected result.
Your columns are same in both tables so u can use union without any changes
for example
select * (select * from TableName1
where Status = 'Success'
union
select * from TableName2
where Status = 'Success'
) A
where count(Status)<10
group by SubUserId, Year, Status
try this.

Duplicates In DataTable, Getting Last By Specifying Two Properties

I have a DataTable, with two columns of type String named ID and Value. These values are not required to be unique.
As I add to my DataTable throughout my application, at some point I am trying to get the last item that was added that meets the value of the two properties. For example, for all records where ID = 1 and Value = 2, there may be several. I need the last record.
I have been trying to use LINQ groupbys, the MyDataTable variable is my datatable.:
var groupQuery = from table in MyDataTable.AsEnumerable()
group table by new {column1 = table["PERSON_GU"], column2 = table["FIELD"]}
into groupedTable
select new
{
x = groupedTable.Key, // Each Key contains column1 and column2
y = groupedTable.Count()
};
I cant figure out how to make this select last though, it appears to return an anonymous type which is a little out of my development skill wheelhouse.
In summary, I have a datatable with two columns, I am trying to group my final datatable by these column values, and then get the last item.
If you want the last DataRow of each group:
var groupQuery =
from table in MyDataTable.AsEnumerable()
group table by new {column1 = table["PERSON_GU"], column2 = table["FIELD"]}
into groupedTable
select groupedTable.Last();

How to Use 'IN' on a DataTable

I have this code in MS SQL:
select * from table where column1 in (select column2 from table)
How can I translate this using a DataTable?
Something along the lines of: table.select("column1 in column2")
you can't.
but you can do it via linq + table.select:
table.Select(string.Format("CITY in '{0}'",string.Join("','",table.Rows.OfType<DataRow>().Select(r=>r["COUNTRY"].ToString()).Distinct())))
EXPLANATION:
suppose you have a very simple table
ID CITY COUNTRY
1 NY USA
2 Moscow Russia
3 LA USA
4 St Peterburg Russia
Using LINQ to Objects we select all unique values from Country column and concatenate values (via string.Join) to the IN filter statement string. For our example it will be USA','Russia
surround IN filter statement with quotes via string.Format: 'USA','Russia'
Pass IN filter in dataTable.Select("CITY IN ('USA','Russia')")
FYI:
If you need to execute really cool SQL queries against DataTables\DataSets you can use NQuery it is very fast and standards compliant.
Assuming the tables are in the same DataSet, you can add a DataRelation to the DataSet and then access the child rows using GetChildRows()
var relation = new DataRelation("RelationName",
dataSet.Tables["Parent"].Columns["Column2"],
dataSet.Tables["Child"].Columns["Column1"]);
dataSet.Relations.Add(relation);
var childRows = from row in dataSet.Tables["Child"].Rows
where row.GetParentRows("RelationName").Length > 0;
You can use the following LINQ to DataSets query to get the same result as the query you have in SQL.
var rows = from r1 in table.AsEnumerable()
from r2 in table.AsEnumerable()
where r1.Field<string>("Column1") == r2.Field<string>("Column2")
select r1;
I assume from your example that the columns are coming from the same table. If not then you just need to change the table in the above as follows.
var rows = from r1 in table1.AsEnumerable()
from r2 in table2.AsEnumerable()
where r1.Field<string>("Column1") == r2.Field<string>("Column2")
select r1;
This is similar to
select * from table1 where column1 in (select column2 from table2)

Categories

Resources