I am having two datatables and my basic need is to know whether the value in a datatable is exist on the another datatable.
My first datatable will contains data like this (id,name,unit)
Second one like this (id,value).
The values may be like this
1-A-b,2-B-c,3-X-d for first one
and 1-2,3,5 for second one. Here 1 and 3 are exsting.How can I find the corresponding values using the id.
this should work;
var table = new DataTable();
table.Columns.Add("id", typeof(int));
table.Columns.Add("name");
table.Columns.Add("unit");
var table2 = new DataTable();
table2.Columns.Add("id", typeof(int));
table2.Columns.Add("value");
table.Rows.Add(1, "a Name", "a Unit");
table.Rows.Add(2, "other", "other");
table2.Rows.Add(1, "value");
table2.Rows.Add(4, "other");
var result = table.AsEnumerable().Join(table2.AsEnumerable(), r1 => r1.Field<int>("id"), r2 => r2.Field<int>("id"),
(r1, r2) => new {Id = r1.Field<int>("id"), Value = r2.Field<string>("value") }).ToList();
foreach (var r in result)
Console.WriteLine(r.Id + "|"+ r.Value);
Related
I have defined a dataTable Like this
DataTable dtFinal = new DataTable();
dtFinal.Columns.Add("AVNR", typeof(int));
dtFinal.Columns.Add("Substation", typeof(string));
dtFinal.Columns.Add("ColumnTitle", typeof(string));
dtFinal.Columns.Add("S6_NAME", typeof(string));
dtFinal.Columns.Add("Voltage", typeof(string));
dtFinal.Columns.Add("Wert", typeof(decimal));
and I make a join between two tables to have a result set
var results = from table1 in dtTimeListTable.AsEnumerable()
join table2 in readyDataTable.AsEnumerable() on (decimal)table1["Avnr"] equals (int)table2["Avnr"]
select new
{
AVNR = (int)table2["AVNR"],
Substation = (string)table2["Substation"],
ColumnTitle = (string)table2["ColumnTitle"],
S6_NAME = (string)table2["S6_NAME"],
Voltage = (string)table2["Voltage"],
Wert = (decimal)table1["Wert"]
};
to fill datatable up I do the following:
dtFinal.Rows.Add(results.ToArray());
but I'll get a error liek this
input array is longer than the number of columns in this table
both datatable have 6 columns, what could be the problem?
DataRowCollection.Add is a method to add a single DataRow but you are trying to add all rows.
You need a loop:
foreach(var x in query)
dtFinal.Rows.Add(x.AVNR, x.Substation, x.ColumnTitle, x.S6_NAME, x.Voltage, x.Wert);
You could build the object[] for each DataRow also in this way:
var joinedRows = from table1 in dtTimeListTable.AsEnumerable()
join table2 in readyDataTable.AsEnumerable() on (decimal) table1["Avnr"] equals (int) table2["Avnr"]
select new { r1 = table1, r2 = table2 };
foreach (var x in joinedRows)
{
object[] fields =
{
x.r2.Field<int>("AVNR"), x.r2.Field<string>("Substation"), x.r2.Field<string>("ColumnTitle"),
x.r2.Field<int>("S6_NAME"), x.r2.Field<string>("Voltage"), x.r1.Field<decimal>("Wert"),
};
dtFinal.Rows.Add(fields);
}
I have created an application where the user can specify queries to databases, maybe even different databases. They would like to have functionality to join the two query results (stored in DataTables) together on user-specified criteria.
The user specifies the join criteria in an XML settings file like this:
<Join Name="join_example" TableAName="tbl_example1" TableBName="tbl_example2" Expression="a.ID == b.ID" />
So far i have converted the DataTables to List of dynamic so the column names are now properties, but I am getting the following error when trying to create the DynamicExpression using those properties:
{"No property or field 'ID' exists in type 'List`1'"}
Any ideas how i can create the dynamic expression? I am open to other ways to perform the join, but would like for the user to be able to use the syntax specified in the XML. Here is my code that is generating the error.
List<dynamic> TableA = ToDynamicList(DataTableA);
List<dynamic> TableB = ToDynamicList(DataTableB);
ParameterExpression paramA = System.Linq.Expressions.Expression.Parameter(TableA.GetType(), "a");
ParameterExpression paramB = System.Linq.Expressions.Expression.Parameter(TableB.GetType(), "b");
Expression Exp = System.Linq.Dynamic.DynamicExpression.Parse(new ParameterExpression[] { paramA, paramB }, TableA.GetType(), this.Expression, new List<dynamic>[] { TableA, TableB });
You don't need to cast the results from tables, you just need to merge them. Here is a linqpad example:
void Main()
{
var dt1 = new DataTable();
dt1.Columns.Add("col1", typeof(string));
dt1.Columns.Add("col2", typeof(int));
var dt2 = new DataTable();
dt2.Columns.Add("col1", typeof(string));
dt2.Columns.Add("col2", typeof(int));
var row = dt1.NewRow();
row["col1"] = "one";
row["col2"] = 1;
dt1.Rows.Add(row);
row = dt1.NewRow();
row["col1"] = "two";
row["col2"] = 2;
dt1.Rows.Add(row);
row = dt2.NewRow();
row["col1"] = "three";
row["col2"] = 3;
dt2.Rows.Add(row);
row = dt2.NewRow();
row["col1"] = "four";
row["col2"] = 4;
dt2.Rows.Add(row);
var dtMerged = dt1.AsEnumerable().CopyToDataTable(); // Note: CopyToDataTable requirs that there are rows. must trap for empty table
dtMerged.Merge(dt2.AsEnumerable().CopyToDataTable(), true, MissingSchemaAction.Add);
dtMerged.Dump();
}
I have this sql query and I want to convert it to linq.
SELECT [Scheme_Code], [FundFamily], [Scheme_Name], MAX([Date]) as LastDate
FROM [MFD].[dbo].[MFDatas]
GROUP BY [Scheme_Code], [Scheme_Name], [FundFamily]
ORDER BY [Scheme_Code]
I want to check last date and if it's latest then I have to mark it as 'live'?
Since you want to copy results to DataTable, this query does what specified in your Sql query and copies results to DataTable.
DataTable dt = new DataTable();
dt.Columns.Add("Scheme_Code", typeof(string));
dt.Columns.Add("Scheme_Name", typeof(string));
dt.Columns.Add("FundFamily", typeof(string));
dt.Columns.Add("LastDate", typeof(DateTime));
var table = MFDatas.GroupBy(g=> new { Scheme_Code, Scheme_Name, FundFamily})
.Select(s=>
{
var row = dt.NewRow();
row["Scheme_Code"] = s.Key.Scheme_Code,
row["Scheme_Name"] = s.Key.Scheme_Name,
row["FundFamily"] = s.Key.FundFamily,
row["LastDate"] = s.Max(m=>m.Date)
})
.OrderBy(o=>o.Field<string>("Scheme_Code"))
.Distinct()
.CopyToDataTable();
I have the following LINQ query :
var groupedData = from b in loans.AsEnumerable()
group b by b.Field<int>("loan_code") & b.Field<int>("emp_num")
into f
select f.CopyToDataTable();
I want to select f and in addition to that the summation of Tot field and copy the result in data table .how to do that?
Get required data
var groupedData = from r in loans.AsEnumerable()
group r by new {
LoanCode = r.Field<int>("loan_code"),
EmpNum = r.Field<int>("emp_num")
} into g
select new {
g.Key.LoanCode,
g.Key.EmpNum,
Tot = g.Sum(r => r.Field<int>("Tot")) // assume integer
};
Then use custom CopyToDataTable method (which works for types that don't implement DataRow) to convert them to DataTable. Or you can build DataTable manually:
DataTable dt = new DataTable();
dt.Columns.Add("loan_code", typeof(int));
dt.Columns.Add("emp_num", typeof(int));
dt.Columns.Add("Tot", typeof(int));
foreach(var data in groupedData)
dt.Rows.Add(data.LoanCode, data.EmpNum, data.Tot);
DataSet oDSetTest = new DataSet();
DataTable oT2 = new DataTable();
oT2.TableName = "Test";
oT2.Columns.Add("ID", typeof(int));
oT2.Columns.Add("Age", typeof(int));
oT2.Columns.Add("Exp", typeof(int));
oT2.Columns.Add("Data", typeof(string));
oT2.PrimaryKey = new DataColumn[] { oT2.Columns["ID"] };
oT2.AcceptChanges();
oT2.Rows.Add(1, 25, 3,"<<AS>>");
oT2.Rows.Add(2, 27, 6);
oT2.Rows.Add(3, 25, 3, "BC");
oDSetTest.Tables.Add(oT2);
oDSetTest.AcceptChanges();
I want to replace "<<" and ">>" in the dataset using the values "<" and ">" respectively using LINQ. I don't want to loop the dataset because in the real scenario there are more than 1000 rows.
You can't avoid loops with LINQ. But here is LINQ solution:
var rowsToUpdate = from r in oT2.AsEnumerable()
let data = r.Field<string>("Data")
where data != null &&
(data.Contains("<<") || data.Contains(">>"))
select r;
foreach (var row in rowsToUpdate)
row.SetField("Data", row.Field<string>("Data")
.Replace("<<", "<").Replace(">>", ">"));
Also keep in mind that LINQ is for Querying, not for modifying. It helps you to select data which you want to modify. Then you should use loop to modify data which will be selected by query.
You can also query on the data filed as follows:
var rows = oDSetTest.Tables["Test"].Select("Data LIKE '%<<%' OR Data LIKE '%>>%'");
foreach (var row in rows)
{
row.SetField("Data", row["Data"].ToString().Replace("<<", "<").Replace(">>", ">"));
}
oDSetTest.AcceptChanges();