How would I write a LINQ query to do the following?
I have a database table with a schema like this:
ID - Int
Time - DateTime
RecordType - Int
Msg - String
I want to get the newest (using 'Time' field) record for each 'RecordType'
Another restriction is that I'm only interested in certain RecordTypes - those contained in an int array.
The result of the query would be one record per RecordType - the newest record for this type.
var results = source.GroupBy(x => x.RecordType)
.Where(g => myRecordTypes.Contains(g.Key))
.Select(g => g.OrderByDescending(x => x.Time).First())
.ToList();
myRecordTypes is int[] with a set of RecordTypes you'd like to get as a result.
result will be List<Record> with one item per RecordType.
You can change to it to be e.g. Dictionary<int, Recort> by RecordType:
var results = source.GroupBy(x => x.RecordType)
.Where(g => myRecordTypes.Contains(g.Key))
.Select(g => new { g.Key, item = g.OrderByDescending(x => x.Time).First() })
.ToDictionary(x => x.Key, x => x.item);
Group them by record types, filter out the ones you want, and then select out the first of the items in that group ordered by time.
int[] recordTypes = GetRecordTypes();
var query = context.Table.GroupBy(item => item.RecordType)
.Where(group => recordTypes.Contains(group.Key))
.Select(group => group.OrderBy(item => item.Time).FirstOrDefault());
Related
My tables here :
In C#
I want to know most repeated 3 categoryName and their count in Blog table, any idea? Thanks
var result = blogs.GroupBy(b => b.CategoryID)
.OrderByDescending(g => g.Count())
.Take(3)
.Select(x => new {CategoryName = x.First().Category.CategoryName, Count = x.Count()})
.ToList();
This will group your blogs by CategoryID, order by count of each grouping, take the top 3 and then select the category name and count of each group as a list.
list.GroupBy(x => x.CategoryName).Select(x => new { x.Key, count = x.Count() }).OrderBy(x => x.count).Take(3);
This will first Group the items by the name.
Then create an anonymous object with the group key (the name) and the Count of all items in every group. Then you order by count and take the first 3.
You could group by category name, order by highest count first and pick the first three results. Example:
Blogs
.GroupBy(b => b.Category.CategoryName)
.OrderByDescending(g => g.Count())
.Take(3)
.Select(x => new { CategoryName = x.Key, Count = x.Count() });
So I have a table like this:
Now I want distinct ShortCode order by the ID descending. In other words, the distinct last records. Like this:
So I tried GroupBy like:
var data = db.ShortCodes.GroupBy(x => x.ShortCode).Select(x => x.FirstOrDefault()).OrderByDescending(s=> s.ID);
This gave me distinct records but not the last ones, nor ordered by ID descending:
Now I also tried like suggested here
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.First())
.OrderByDescending(s => s.ID);
This gave me the error The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
So I modified to FirstOrDefault() like:
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.FirstOrDefault())
.OrderByDescending(s => s.ID);
This also gave me distinct records but not the last records:
So finally I tried like suggested here:
var data = db.ShortCodeManager.Where(a => a.ID > 0).GroupBy(x => x.ShortCode).OrderByDescending(grp => grp.Max(g => g.ID)).Select(a => a.FirstOrDefault());
Again, this gave me distinct records but not the last ones, nor ordered by ID descending:
So how am I to write the query to get the result I want in Linq? Also note, I need more of the distinct last records than ordering by ID descending. If anyone also knows how to write it in raw SQL it might be useful as well.
This LINQ query should work for your case:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
EDIT:
Based on your comment it looks like you need to cast anonymous object result to ShortCodeManagerModel type and then pass it to your view. So, somethin like this:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
var model = result
.Select(x => new ShortCodeManagerModel { Id = x.Id, ShortCode = x.ShortCode })
.ToList();
And then pass model to you view.
I have a list. I want to separate the list in pieces by (partionCountValue)variable. And I want to group data by a date value. And the data with the same date must be in the same pieces. I could not group the same date in the same group. How can I do this?
My example code:
var list = lstHareket.Select((x,i) => new { Index = i, Value = x})
.GroupBy(x => x.Index / partionCountValue)
.Select(x => x.Select(v => v.Value).ToList()
).ToList();
If I have a set of entities with 3 properties (Id, Type, Size) all of which are strings.
Is there a way using Linq to Entities where I can do a group query which gives me the Size + Type as the key and then a list of the related Id's for that Size + Type?
Example below of getting the count:
Items.GroupBy(x => new { x.Size, x.Type})
.Select(x => new { Key = x.Key, Count = x.Count() })
but I am looking to get a list of the Ids for each grouping?
I am looking to see if it is possible using Linq-to-EF before I decide to iterate through this in code and build up the result instead.
If you want to get List of Ids for each group then you have to select x.Select(r => r.Id) like:
var result = Items.GroupBy(x => new { x.Size, x.Type })
.Select(x => new
{
Key = x.Key,
Ids = x.Select(r => r.Id)
});
Another way to build up a Dictionary<string, IEnumerable<string?>> in dotnet 6.0 according to the docs;
where we have the dictionary Key as {Size, Type} and Value the list of Ids, you can write:
Dictionary<string, IEnumerable<string?>> result = Items.GroupBy(item => new { item.Size, item.Type }
item => item.Id),
(itemKey, itemIds) =>
{
Key = itemKey,
Ids = itemIds
})
.ToDictionary(x => x.Key, x=> x.Ids);
When using the below code it works fine to return a var that is filled with DataRows I can loop:
var GetSetRows = Order.AsEnumerable()
.GroupBy(r => r.Field<string>("Job_No"))
.Where(g => g.Count() > 1)
.Select(g => g.First());
but what I would like to do is return a List<string> instead.
I tried:
List<string> c_strLSetTitle = Order.AsEnumerable()
.GroupBy(r => r.Field<string>("Job_No"))
.Where(g => g.Count() > 1)
.Select(g => g.First().ToString()).ToList();
but this returns a list filled with elements that say System.Data.DataRow, but it does return the correct amount, i.e. that amount of items that I am expecting to be returned.
g.First() returns object of type DataRow. Then you are calling ToString() which returns the type name System.Data.DataRow. At the end you have a list of type names.
If you want to select a particular column, then project group of rows into value of some field of (first) row:
g.First().Field<string>("FieldName")
Or you can use grouping key if you want to return values of Job_No filed:
List<string> c_strLSetTitle = Order.AsEnumerable()
.GroupBy(r => r.Field<string>("Job_No"))
.Where(g => g.Count() > 1)
.Select(g => g.Key).ToList();
That will return values of duplicated Job_No fields.
Because g is a collection of DataRow objects, so
.Select(g => g.First().ToString())
returns a collection of the string System.Data.DataRow
If you want to extract a field from each datarow, then use:
.Select(g => g.First().Field<{type}>("{fieldname}").ToString())
try this
List<string> c_strLSetTitle = Order.AsEnumerable()
.GroupBy(r => r.Field<string>("Job_No"))
.Where(g => g.Count() > 1)
.Select(g => g.Key).ToList();