I want to use Linq to select and group DataTable rows... and I want to order those in a descending manner by the "Max" created date in each group... are there any improvements that could be made to this code, in particular can I make the OrderByDescending part of the Linq, for example using:
orderby {... something here...} descending
--- current code ---
DataTable dt = ReadDataTable();
var rows = (from row in dt.AsEnumerable()
where row.Field<bool>("Active") == true
group row by new
{
CollectionId = row.Field<int>("CollectionId"),
CollectionName = row.Field<string>("CollectionName"),
} into grp
select new
{
CollectionId = grp.Key.CollectionId,
CollectionName = grp.Key.CollectionName,
MaxCreated = grp.Max(r => r.Field<DateTime>("Created"))
}).OrderByDescending(r => r.MaxCreated);
You can use the let clause to hold intermediate results in a complex LINQ query, for use in subsequent sorts and selects. In your case you can use it to store the final result for subsequent sorting.
I.e. you can rewrite your Linq without the OrderByDescending() lambda as follows:
DataTable dt = ReadDataTable();
var rows = from row in dt.AsEnumerable()
where row.Field<bool>("Active")
group row by new
{
CollectionId = row.Field<int>("CollectionId"),
CollectionName = row.Field<string>("CollectionName"),
} into grp
let result = new
{
CollectionId = grp.Key.CollectionId,
CollectionName = grp.Key.CollectionName,
MaxCreated = grp.Max(r => r.Field<DateTime>("Created")),
}
orderby result.MaxCreated descending
select result;
Related
I have the following code but am having issues with how to maintain the order:
var cars = (from DataRow dRow in dt.AsEnumerable()
select new
{
Car = dRow["Car"],
CarId = dRow["CarId"],
CarOrder = dRow["CarOrder"]
}).Distinct();
The distinct works well but I need to preserver the CarOrder which goes from 1 to X (ascedning).
The DataTable dt have them all in order correctly but when it hits this distinct code the order does not get preserved.
I am trying to figure out how to use the OrderBy clause.
According to docs
It returns an unordered sequence of the unique items in source
That means that order does not get preserved. So what you can do is probably OrderBy() after the Distinct() as following:
var cars = (from DataRow dRow in dt.AsEnumerable()
select new
{
Car = dRow["Car"],
CarId = dRow["CarId"],
CarOrder = dRow["CarOrder"]
}).Distinct().OrderBy(x => x.CarOrder);
See: Does Distinct() method keep original ordering of sequence intact?
I want to assign an var query value to a (DataGrid)dgEntity without DataTable
How can i do it?
var query = (from c in db.CUSTOMERS.Local
let avg = (from o2 in db.CITIES.Local
join o3 in db.CUSTOMERS.Local on o2.CITNUM equals o3.CITNUM
where (o2.CITY == "Ярославль")
select new { o3.RATING }).Average(t => t.RATING)
where (c.RATING>avg)
select new
{
cusnum = c.CUSNUM
}).Count();
DataTable d = new DataTable();
d.Columns.Add("Count");
d.Rows.Add(new object[] { query });
dgEntity.ItemsSource = d.DefaultView;
Unless I am missing something the result of Count() is getting assigned to query which is just an int and not enumerable. Can you try taking Count() off of the linq query?
I want to obtain the distinct count of a column in my data table.
I have the following so far
public int DocumentsProcessed()
{
var query = from data in this._data
let docID = data.Field<string>("Document ID")
select new
{
docID
};
var query2 = from d in query
select d.docID.Distinct().Count();
var result = query2;
return result;
}
where this._data is
private IEnumerable<DataRow> _data;
But the result is an IEnumerable. I'm looking for just a single integer as an answer.
EDIT: I tried grouping the data first by Document ID column and then counting the groups, but it gave me the wrong number - for example I have 16 rows where all the Document ID are the same, so the Distinct count should be 1 but I was getting 16.
So in your example for every row you're doing a select distinct. I believe what you want is:
var query = from data in this._data
let docID = data.Field<string>("Document ID")
select new
{
docID
};
var distinctCount = query.Distinct().Count();
I suppose that data is DataTable object so try it in this manner
int count = _data.
.AsEnumerable()
.Select(r => r.Field<string>("Document ID"))
.Distinct()
.Count();
I am trying to write a linq query for one of my dashboard which retrieves data based on some conditions. I want to display records count based on the different status available in my table.
Following is the SQL query in which I am trying to convert into Linq.
select count(id) cnt, 'Available' label from table where date = sysdate
Above query is returning below result in DB IDE. This is the result I want with linq
cnt label
0 Available
I've tried with following linq query but it is returning 0 count and hence result is not being retrieved.
var data = (from a in context
where a.date = System.DateTime.Now
group a in a.id into g
select new {
cnt = g.Count(),
label = 'Available'
}).ToList();
How do I achieve above mentioned result in linq. Your help will be appreciated.
Thanks
-------------EDIT----------------
Updated LINQ query
var data = (from a in context.TableA
where a.id = uniqueID
group a in a.id into g
select new {
cnt = g.Count(),
label = 'Available'
}).Concat(from a in context.TableB
where a.id = uniqueID
group a in a.id into g
select new {
cnt = g.Count(),
label = 'WIP'
}).ToList();
To count the number of elements matching a predicate in a linq query simply use the where clause:
var results =
from a in context
where a.date.Date == DateTime.Now.Date
&& a.id == someIdHere
select a;
var data = new {
count = results.Count(),
label = "Available"
};
Or, in extension method syntax (which I prefer):
var results = context.Where(a => a.date.Date == DateTime.Now.Date && a.id == someIdHere);
var data = new {
count = results.Count(),
label = "Available"
};
Also be careful when comparing a DateTime object with regards to what results you desire; comparing DateTime.Now to a date will likley return false since it will compare the time code as well, use the DateTime.Date property to obtain only the date from the object for the purposes of comparison.
How would the following be converted to LINQ-EF
select Name
from TableA as TableAOuter
group by TableAOuter.Name, TableAOuter.Id
having(
select count(TableAInner.Id)
from TableA as TableAInner
where TAbleAInner.Reference=TableAOuter.Id) = 0
);
To me, that looks like:
var query = from row in tableOuter
group row by new { row.Name, row.Id } into g
where !tableInner.Any(inner => inner.Reference == g.Key.Id)
select g.Key.Name;
Although I'd be tempted to perform the filtering before the grouping - at which point you can just group the row name:
var query = from row in tableOuter
where !tableInner.Any(row => inner.Reference == row.Id)
group row.Name by new { row.Name, row.Id };
I think that should do the same thing, right?