Delete using LINQ by joining two datatables - c#

I have two datatable DurationByCurrency(inside a dataset) and Fund which looks like below
I want to delete the rows in Duration By Currency Datatable whose FundCode has value as 2 in Fund Dt by performing a join.
var result = from table1 in raptorDS.Tables[RaptorTable.DurationByCurrency].AsEnumerable()
join table2 in fundDT.AsEnumerable()
on table1.Field<string>("FundCode") equals table2.Field<string>("FundCode") into ps
from row in ps.DefaultIfEmpty()
{
//delete query
}
Please help me on this as I am new to LINQ.

var result = from row1 in raptorDS.Tables[RaptorTable.DurationByCurrency].AsEnumerable()
join row2 in fundDT.AsEnumerable()
on row1.Field<string>("FundCode") equals row2.Field<string>("FundCode")
where row1.Field<string>("value")
equals "2" select row1;
result.ToList().ForEach(row => row.Delete());
sample test code for linqpad:
void Main()
{
//sample data for test
DataSet ds = new DataSet();
ds.Tables.Add(GetTable1());
ds.Tables.Add(GetTable2());
var result = ( from rec1 in ds.Tables[0].AsEnumerable()
join rec2 in ds.Tables[1].AsEnumerable()
on rec1.Field<string>("FC") equals rec2.Field<string>("FC")
where rec2.Field<int>("Value") == 2 select rec1);
result.ToList().ForEach(row => row.Delete());
//now you have only "ABCD" and "AZY" in table 1
//ds.Tables[0].Dump(); linqpad display result
}
DataTable GetTable1()
{
DataTable table = new DataTable();
table.Columns.Add("FC", typeof(string));
table.Rows.Add("ABCD");
table.Rows.Add("XYZ");
table.Rows.Add("AZY");
return table;
}
DataTable GetTable2()
{
DataTable table = new DataTable();
table.Columns.Add("FC", typeof(string));
table.Columns.Add("Value", typeof(int));
table.Rows.Add("ABCD", 1);
table.Rows.Add("XYZ", 2);
table.Rows.Add("AZY",3);
return table;
}

Related

Merge two datatables?

I want to merge two data table in which column "ID" as primary key in both table.
Note: Both table has two column as "ID, Name" & "ID, name" where Name & name is case sensitive.
Table: 1
Table: 2
Expected Merged Table Result:
Code:
public MainWindow()
{
InitializeComponent();
// Table 1
DataTable table1 = new DataTable();
table1.Columns.Add("ID", typeof(int));
table1.Columns.Add("Name", typeof(String));
table1.PrimaryKey = new DataColumn[] { table1.Columns["ID"] };
table1.Rows.Add(1, "A");
table1.Rows.Add(4, "D");
table1.Rows.Add(5, "E");
// Table 2
DataTable table2 = new DataTable();
table2.Columns.Add("ID", typeof(int));
table2.Columns.Add("name", typeof(String));
table2.PrimaryKey = new DataColumn[] { table2.Columns["ID"] };
table2.Rows.Add(1, "A");
table2.Rows.Add(2, "B");
table2.Rows.Add(3, "C");
table2.Rows.Add(5, "E");
table1.Merge(table2);
}
Please help me to achieve this expected result.
You could temporarily change the name of the second column and still use Merge:
const string OriginalName = "name";
const string TemporaryName = "temp";
table2.Columns[OriginalName].ColumnName = TemporaryName;
table1.Merge(table2);
table1.Columns[TemporaryName].ColumnName = OriginalName;
table2.Columns[TemporaryName].ColumnName = OriginalName;
Use this:
DataTable dtResult = new DataTable();
dtResult.Columns.Add("ID", typeof(int));
dtResult.Columns.Add("Name", typeof(string));
dtResult.Columns.Add("name", typeof(string));
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<int>("ID") equals dataRows2.Field<int>("ID")
into rows
from row in rows.DefaultIfEmpty()
select dtResult.LoadDataRow(new object[]
{
dataRows1.Field<int>("ID"),
dataRows1.Field<string>("Name"),
dataRows2.Field<string>("name")
}, false);

How to use Linq to join multiple DataTables on multiple columns containing DBNull values

I have 3 DataTable objects with relational data that I want to join.
The first has a schema that looks like
DataTable parent = new DataTable();
parent.Columns.Add("Id1", typeof(string));
parent.Columns.Add("Id2", typeof(string));
// more metadata
Where either of the Ids may be DBNull, but not both.
The two chlid tables have the same schema.
DataTable child = new DataTable();
child.Columns.Add("Id1", typeof(string));
child.Columns.Add("Id2", typeof(string));
child.Columns.Add("BeginDate", typeof(DateTime));
child.Columns.Add("SomeData", typeof(float));
// more data
I have a function that takes all three DataTables as inputs, and is supposed to return the joined table.
var dataToReturn = // will be converted to a DataTable later.
from
p in parent.AsEnumerable()
join c1 in child1.AsEnumerable()
on new {
Id1 = p["Id1"],
Id2 = p["Id2"],
}
equals new {
Id1 = c1["Id1"],
Id2 = c1["Id2"],
}
join c2 in child2.AsEnumerable()
on new {
Id1 = p["Id1"],
Id2 = p["Id2"],
BeginDate = c1["BeginDate"],
}
equals new {
Id1 = p["Id1"],
Id2 = p["Id2"],
BeginDate = c1["BeginDate"],
}
select new {
Id1 = p["Id1"],
Id2 = p["Id2"],
BeginDate = c1["BeginDate"],
Child1Data = c1["SomeData"],
Child2Data = c2["SomeData"],
}
However, this returns no results, even though there are many non-null values matching on those conditions.
If I were writing SQL (with "is not distinct from" from Postgres to make null = null return true for brevity), I would write
select
p.Id1,
p.Id2,
c1.BeginDate,
c1.SomeData as Child1Data,
c2.SomeData as Child2Data
from
Parent p
join Child1 c1
on c1.Id1 is not distinct from p.Id1
and c1.Id2 is not distinct from p.Id2
join Child2 c2
on c2.Id1 is not distinct from p.Id1
and c2.Id2 is not distinct from p.Id2
and c2.BeginDate = c1.BeginDate
Notice the use of "is not distinct from" over "=" for the Id fields, since I want "DBNull.Value == DBNull.Value" to return true.
My questions:
Is this possible to do with in-memory DataTables with Linq?
How does Linq handle DBNull.Value comparisons in these queries?
Linq will match DBNull.Value to another DBNull.Value correctly. I believe that was your question and not joining a second child table as this is trivial
DataTable parent = new DataTable();
parent.Columns.Add("Id1", typeof(string));
parent.Columns.Add("Id2", typeof(string));
DataRow r1 = parent.NewRow();
r1["Id1"] = "1";
r1["Id2"] = DBNull.Value;
parent.Rows.Add(r1);
DataRow r3 = parent.NewRow();
r3["Id1"] = "1";
r3["Id2"] = "2";
parent.Rows.Add(r3);
DataTable child1 = new DataTable();
child1.Columns.Add("Id1", typeof(string));
child1.Columns.Add("Id2", typeof(string));
child1.Columns.Add("BeginDate", typeof(DateTime));
child1.Columns.Add("SomeData", typeof(float));
DataRow r2 = child1.NewRow();
r2["Id1"] = "1";
r2["Id2"] = DBNull.Value;
child1.Rows.Add(r2);
DataRow r4 = child1.NewRow();
r4["Id1"] = "1";
r4["Id2"] = "2";
child1.Rows.Add(r4);
var dataToReturn =
from
p in parent.AsEnumerable()
join c1 in child1.AsEnumerable()
on new { Id1 = p["Id1"], Id2 = p["Id2"] }
equals new { Id1 = c1["Id1"], Id2 = c1["Id2"] }
select new
{
Id1 = p["Id1"],
Id2 = p["Id2"]
};
foreach(var l in dataToReturn)
{
Console.WriteLine(l.Id1 + "|" + l.Id2);
}
Console.ReadKey();
Output:
1|
1|2

compare two datatables with multiple columns with a unique id

I have written a program to compare two datatables with unique ids and create another datatable to insert certain columns which have the same id in common. I have demonstrated my requirement below.
These are the tables that needs to be compared:
And i need the output as below
but i receive an empty table as the result. I cannot understand where have i gone wrong. Could you please help me on this. I have provided my coding below.Please not that quantity and input are two datatables
DataTable result = new DataTable();
result.Columns.AddRange(new DataColumn[2] { new DataColumn("id"), new DataColumn("qty") });
foreach (DataRow row1 in input.Rows)
{
foreach (DataRow row2 in quantity.Rows)
{
if (row1["id"].ToString() == row2["id"].ToString())
{
result.ImportRow(row2);
}
else
{
result.ImportRow(row1);
}
}
}
return result;
You need a Left Join of 2 Data tables.
DataTable dtinput = new DataTable();
DataTable dtquantity = new DataTable();
dtinput.Columns.Add("id",typeof(int));
dtinput.Rows.Add("2");
dtinput.Rows.Add("4");
dtinput.Rows.Add("7");
dtquantity.Columns.Add("id", typeof(int));
dtquantity.Columns.Add("qty", typeof(int));
dtquantity.Rows.Add("1", "12");
dtquantity.Rows.Add("2", "13");
dtquantity.Rows.Add("3", "5");
dtquantity.Rows.Add("4", "6");
dtquantity.Rows.Add("7", null);
var results = from table1 in dtinput.AsEnumerable()
join table2 in dtquantity.AsEnumerable()
on (int)table1["id"] equals (int)table2["id"]
into outer
from row in outer.DefaultIfEmpty<DataRow>()
select row;
DataTable dt = results.CopyToDataTable();
This diagram should help you in future:
Try something like this:
var result = input.Rows.Where(x => quantity.Rows.Amy(y => x == y));
I hope this helps!

How to populate DataTable with anonymous LINQ result

I have the following LINQ query:
var timesheets = from timesheet in entities.Timesheets
join timesheetTask in entities.Timesheet_Task on timesheet.Id equals timesheetTask.Timesheet_Id
join task in entities.Tasks on timesheetTask.Task_Id equals task.Id
join project in entities.Projects on task.Project_Id equals project.Id
join department in entities.Departments on project.Department_Id equals department.Id
where timesheet.Employee_Id == employeeId
select new
{
date = timesheet.Date,
taskName = task.Name,
projectName = project.Name,
projectDesc = project.Description,
departmentName = department.Name,
taskEstimatedHours = task.Estimated_Hours,
timesheetHours = timesheetTask.Hours
};
How can I put these results into a DataTable which I can then bind to a DataGridView control?
This is what I'm currently doing:
table.Columns.Add("date");
table.Columns.Add("taskName");
table.Columns.Add("projectName");
table.Columns.Add("projectDesc");
table.Columns.Add("departmentName");
table.Columns.Add("taskEstimatedHours");
table.Columns.Add("timesheetHours");
foreach (var item in timesheets)
{
table.Rows.Add(item.date, item.taskName, item.projectName,
item.projectDesc, item.departmentName, item.taskEstimatedHours,
item.timesheetHours);
}
}
Update: Here is my updated code:
DataTable table = new DataTable();
using (PTMS_DataEntities entities = new PTMS_DataEntities())
{
var timesheets = from timesheet in entities.Timesheets
join timesheetTask in entities.Timesheet_Task on timesheet.Id equals timesheetTask.Timesheet_Id
join task in entities.Tasks on timesheetTask.Task_Id equals task.Id
join project in entities.Projects on task.Project_Id equals project.Id
join department in entities.Departments on project.Department_Id equals department.Id
where timesheet.Employee_Id == employeeId
select new
{
date = timesheet.Date,
taskName = task.Name,
projectName = project.Name,
projectDesc = project.Description,
departmentName = department.Name,
taskEstimatedHours = task.Estimated_Hours,
timesheetHours = timesheetTask.Hours
};
table.Columns.Add("date", typeof(DateTime));
table.Columns.Add("taskName", typeof(string));
table.Columns.Add("projectName", typeof(string));
table.Columns.Add("projectDesc", typeof(string));
table.Columns.Add("departmentName", typeof(string));
table.Columns.Add("taskEstimatedHours", typeof(int));
table.Columns.Add("timesheetHours", typeof(int));
List<DataRow> list = new List<DataRow>();
foreach (var item in timesheets)
{
//table.Rows.Add(item.date, item.taskName, item.projectName,
// item.projectDesc, item.departmentName, item.taskEstimatedHours,
// item.timesheetHours);
var row = table.NewRow();
row.SetField<DateTime>("date", item.date);
row.SetField<string>("taskName", item.taskName);
row.SetField<string>("projectName", item.projectName);
row.SetField<string>("projectDesc", item.projectDesc);
row.SetField<string>("departmentName", item.departmentName);
row.SetField<int>("taskEstimatedHours", item.taskEstimatedHours);
row.SetField<int>("timesheetHours", item.timesheetHours);
list.Add(row);
}
table = list.CopyToDataTable();
}
Here is the SQL query I tested in SSMS (which should be the equivalent of the LINQ query):
SELECT dbo.Department.Name, dbo.Task.Name AS Expr1, dbo.Task.Estimated_Hours, dbo.Timesheet.Date, dbo.Project.Name AS Expr2, dbo.Project.Description,
dbo.Timesheet_Task.Date AS Expr3
FROM dbo.Department INNER JOIN
dbo.Project ON dbo.Department.Id = dbo.Project.Department_Id INNER JOIN
dbo.Task ON dbo.Project.Id = dbo.Task.Project_Id INNER JOIN
dbo.Timesheet_Task ON dbo.Task.Id = dbo.Timesheet_Task.Task_Id INNER JOIN
dbo.Timesheet ON dbo.Timesheet_Task.Timesheet_Id = dbo.Timesheet.Id
If you really want to populate DataTable:
// your query
var timesheets = ...
// design table first
DataTable table = new DataTable();
table.Columns.Add(new DataColumn
{
ColumnName = "TaskName",
DataType = typeof(String);
});
...
List<DataRow> list = new List<DataRow>();
foreach (var t in timesheets)
{
var row = table.NewRow();
row.SetField<string>("TaskName", t.taskName); // extension method from System.Data.DataSetExtensions.dll
...
list.Add(row);
}
DataTable table = list.CopyToDataTable(); // extension method too
Or more LINQ way:
timesheets
.Select(t =>
{
var row = table.NewRow();
...
return row;
})
.CopyToDataTable();
Or in same query syntax. Implement a method:
static DataRow NewRow(DataRow row, string taskName, ....)
{
...
}
Then query itself:
(from ...
where ...
select NewRow(table.NewRow(), task.Name, ...)
).CopyToDataTable();
Call .ToList().
The resulting List<T> can also be bound to a DataGridView, and is easier to work with than a DataTable.
I'm using FastMember for this purpose. It uses IL instead of reflection (much faster) to iterate over all of the property and field values automatically. Code sample from the site:
IEnumerable<SomeType> data = ...
var table = new DataTable();
using(var reader = ObjectReader.Create(data))
{
table.Load(reader);
}

merge 2 datatable

I have 2 Datatable dt and dt2
var dt = MultiCheckCombo3.GetAllChechedBox();
var dt2 =manager.GetAllStudents(student_id, classid);
In the first table dt are two columns "id_staff" and "name_staff"
In the second table are several columns but 2 of them repeat "id_staff" and "name_staff"
I want to create a new DataTable with the fields "id_staff" and "name_staff" common DataTable dt and dt2
how joined these tables?
dt3= dt+dt2
You can use Linq to join the two tables. See the following example.
Code from the article:
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
Have a look at the DataTable.Merge method:
This link from Microsoft has an example of how to do this
If dt and dt2 are DataTables, you can use datatable merge.
DataTable dt3 = dt.Copy()
dt3.Merge(dt2, false, MissingSchemaAction.Ignore)
Maybe something like this:
var dt=new DataTable();
dt.Columns.Add("id_staff",typeof(int));
dt.Columns.Add("name_staff",typeof(string));
var dt2=new DataTable();
dt2.Columns.Add("id_staff",typeof(int));
dt2.Columns.Add("name_staff",typeof(string));
dt.Rows.Add(1,"test");
dt2.Rows.Add(2,"test2");
var result=
(
from datatable1 in dt.AsEnumerable()
select new
{
id_staff=datatable1.Field<int>("id_staff"),
name_staff=datatable1.Field<string>("name_staff")
}
).Concat
(
from datatable2 in dt2.AsEnumerable()
select new
{
id_staff=datatable2.Field<int>("id_staff"),
name_staff=datatable2.Field<string>("name_staff")
}
);

Categories

Resources