I have an entity set of Publications with a ReleaseDate property. I would like to get a List of all distinct year-&-month combos from this set for the purpose of creating a pagination widget.
Preferably, I'd like a list of DateTime values with the day as 1 for each distinct year-month from my publications set:
IEnumerable<DateTime> DistinctYearMonths = from p in context.Publications. .... ?
How can I finish this linq-to-entities query?
IEnumerable<DateTime> DistinctYearMonths = context.Publications
.Select(p => new { p.ReleaseDate.Year, p.ReleaseDate.Month })
.Distinct()
.ToList() // excutes query
.Select(x => new DateTime(x.Year, x.Month, 1)); // copy anonymous objects
// into DateTime in memory
The intermediate step to project into an anonymous type is necessary because you cannot directly project into a DateTime (constructors with parameters are not supported in projections in LINQ to Entities and the Year and Month properties of DateTime are readonly, so you can't set them with initializer syntax (new DateTime { Year = p.ReleaseDate.Year, ... } is not possible)).
Try the following query:
(from p in publications
select new DateTime(p.ReleaseDate.Year, p.ReleaseDate.Month, 1)).Distinct();
Using Group By:
(from i in context.Publications
group i by new { i.ReleaseDate.Year, i.ReleaseDate.Month } into g
select g.Key).ToList().Select(i => new DateTime(i.Year, i.Month, 1));
var DistinctYearMonths = context.Publications
.Select(x => new DateTime(x.ReleaseDate.Year, x.ReleaseDate.Month, 1))
.Distinct()
.ToList()
I like chained linq methods much better than the long form. They're much easier to read IMO.
var DistinctYearMonths = (from p in context.Publications
select new DateTime(p.ReleaseDate.Year,
p.ReleaseDate.Month,
1)).Distinct();
Related
If have a directory with files that are created on different dates. I want to get the dates.
Is it possible to do this with a linq query, or must I first read all the files and use a foreach loop to get the dates.
Example:
List =
File_1 6/03/2016
File_2 6/03/2016
File_3 6/03/2016
File_4 6/03/2016
File_5 15/04/2016
File_6 21/04/2016
File_7 21/04/2016
File_8 21/04/2016
Result =
6/03/2016
15/04/2016
21/04/2016
Thanks
Based on the comment from #MatthewWatson.
I have make following linq statement
var dateInfo = Directory.EnumerateFiles(Dir).Select(filename => new FileInfo(filename)).Select(i => new { i.LastWriteTime }).GroupBy(g => g.LastWriteTime.Date);
That way I get all the different dates used in my directory.
Clearly you can't process the list of dates without iterating it, but you can use Linq to produce the sequence in the first place, like so:
var dateInfo =
Directory.EnumerateFiles(directoryName)
.Select(filename => new FileInfo(filename))
.Select(info => new {info.Name, info.CreationTime});
That'll give you a list of FullName/CreationTime pairs, where FullName is the full path of the file, and CreationTime is the creation time of the file.
You can process it like so:
foreach (var item in dateInfo)
Console.WriteLine($"{item.FullName} created on {item.CreationTime}");
If you just want the (unique) dates that the files were created on:
var uniqueDates = dateInfo.GroupBy(x => x.CreationTime.Date).Select(y => y.Key);
foreach (var date in uniqueDates)
Console.WriteLine(date);
Finally, if you need the dates to be ordered:
var uniqueDates =
dateInfo.GroupBy(x => x.CreationTime.Date)
.Select(y => y.Key)
.OrderBy(z => z);
(And use .OrderByDescending() for the reverse order, of course.)
If you prefer Linq query syntax:
var uniqueDates =
from date in dateInfo
group date by date.CreationTime.Date into g
orderby g.Key
select g.Key;
Or putting the entire thing in one Linq query (maybe getting a bit unreadble here, so you might want keep it as separate queries, but this is for completeness):
var uniqueDates =
from date in
from file in Directory.EnumerateFiles(directoryName)
select new FileInfo(file).CreationTime
group date by date.Date into g
orderby g.Key
select g.Key;
SELECT
[TimeStampDate]
,[User]
,count(*) as [Usage]
FROM [EFDP_Dev].[Admin].[AuditLog]
WHERE [target] = '995fc819-954a-49af-b056-387e11a8875d'
GROUP BY [Target], [User] ,[TimeStampDate]
ORDER BY [Target]
My database table has the columns User, TimeStampDate, and Target (which is a GUID).
I want to retrieve all items for each date for each user and display count of entries.
The above SQL query works. How can I convert it into LINQ to SQL? Am using EF 6.1 and my entity class in C# has all the above columns.
Create Filter basically returns an IQueryable of the entire AuditLogSet :
using (var filter = auditLogRepository.CreateFilter())
{
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => i.Target, i => i.User, i => i.TimeStamp);
audits = query.ToList();
}
Am not being allowed to group by on 3 columns in LINQ and I am also not sure how to select like the above SQL query with count. Fairly new to LINQ.
You need to specify the group by columns in an anonymous type like this:-
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(x => new { x.User, x.TimeStampDate })
.Select(x => new
{
TimeStampDate= x.Key.TimeStampDate,
User = x.Key.User,
Usage = x.Count()
}).ToList();
Many people find query syntax simpler and easier to read (this might not be the case, I don't know), here's the query syntax version anyway.
var res=(from it in filter.All
where it.Target=="995fc819-954a-49af-b056-387e11a8875d"
group it by new {it.Target, it.User, it.TimeStampDate} into g
orderby g.Key.Target
select new
{
TimeStampDate= g.Key.TimeStampDate,
User=g.Key.User,
Usage=g.Count()
});
EDIT: By the way you don't need to group by Target neither OrderBy, since is already filtered, I'm leaving the exact translation of the query though.
To use GroupBy you need to create an anonymous object like this:
filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => new { i.Target, i.User, i.TimeStamp });
It is unnecessary to group by target in your original SQL.
filter.All.Where( d => d.Target == "995fc819-954a-49af-b056-387e11a8875d")
.GroupBy(d => new {d.User ,d.TimeStampDate} )
.Select(d => new {
User = d.Key.User,
TimeStampDate = d.Key.TimeStampDate,
Usage = d.Count()
} );
I have a class and its List
abc cs = new abc();
List<abc> Lst_CS = new List<abc>();
and I set some value by HidenField in foreach loop
foreach (blah blah)
{
cs = new abc{
No = VKNT,
GuidID=hdnGuidID.Value.ToString(),
RecID=hdnRecID.Value.ToString(),
Date=HdnDate.Value.ToString()
};
Lst_CS.Add(cs);
}
and finally I get a List_CS and I order by Lst_CS according to Date like this;
IEnumerable<abc> query = Lst_CS.OrderBy(l => l.Date).ToList();
but in extra, I want to group by according to No.
Briefly, I want to order by Date and then group by No on Lst_CS How can I do ?
Thanks for your answer
Well you just just do the ordering then the grouping like so:
Lst_CS.OrderBy(l => l.Date)
.GroupBy(l => l.No)
.ToList();
Each list of items in each group will be ordered by date. The groupings will be in the order that they are found when the entire list is ordered by date.
Also your ForEach can be done in one Linq statement, then combined with the ordering and grouping:
var query = blah.Select(b => new abc{
No = VKNT,
GuidID=hdnGuidID.Value.ToString(),
RecID=hdnRecID.Value.ToString(),
Date=HdnDate.Value.ToString()
})
.OrderBy(l => l.Date)
.GroupBy(l => l.No)
.ToList();
I have the following block of code which works fine;
var boughtItemsToday = (from DBControl.MoneySpent
bought in BoughtItemDB.BoughtItems
select bought);
BoughtItems = new ObservableCollection<DBControl.MoneySpent>(boughtItemsToday);
It returns data from my MoneySpent table which includes ItemCategory, ItemAmount, ItemDateTime.
I want to change it to group by ItemCategory and ItemAmount so I can see where I am spending most of my money, so I created a GroupBy query, and ended up with this;
var finalQuery = boughtItemsToday.AsQueryable().GroupBy(category => category.ItemCategory);
BoughtItems = new ObservableCollection<DBControl.MoneySpent>(finalQuery);
Which gives me 2 errors;
Error 1 The best overloaded method match for 'System.Collections.ObjectModel.ObservableCollection.ObservableCollection(System.Collections.Generic.List)' has some invalid arguments
Error 2 Argument 1: cannot convert from 'System.Linq.IQueryable>' to 'System.Collections.Generic.List'
And this is where I'm stuck! How can I use the GroupBy and Sum aggregate function to get a list of my categories and the associated spend in 1 LINQ query?!
Any help/suggestions gratefully received.
Mark
.GroupBy(category => category.ItemCategory); returns an enumerable of IGrouping objects, where the key of each IGrouping is a distinct ItemCategory value, and the value is a list of MoneySpent objects. So, you won't be able to simply drop these groupings into an ObservableCollection as you're currently doing.
Instead, you probably want to Select each grouped result into a new MoneySpent object:
var finalQuery = boughtItemsToday
.GroupBy(category => category.ItemCategory)
.Select(grouping => new MoneySpent { ItemCategory = grouping.Key, ItemAmount = grouping.Sum(moneySpent => moneySpent.ItemAmount);
BoughtItems = new ObservableCollection<DBControl.MoneySpent>(finalQuery);
You can project each group to an anyonymous (or better yet create a new type for this) class with the properties you want:
var finalQuery = boughtItemsToday.GroupBy(category => category.ItemCategory);
.Select(g => new
{
ItemCategory = g.Key,
Cost = g.Sum(x => x.ItemAmount)
});
The AsQueryable() should not be needed at all since boughtItemsToday is an IQuerable anyway. You can also just combine the queries:
var finalQuery = BoughtItemDB.BoughtItems
.GroupBy(item => item.ItemCategory);
.Select(g => new
{
ItemCategory = g.Key,
Cost = g.Sum(x => x.ItemAmount)
});
I am trying to create a lambda expression (Linq, C# 3.5) that can perform a OrderBy on a value that is of data type String but which actually contains a parse-able DateTime.
For example, typical values may be "5/12/2009" , "1/14/2008", etc.
The OrderBy clause below works correctly for ordering (as if string data), but I actually want to treat the values as DateTimes, and perform the sort by Date. (The sortColumn would be something like "dateCreated".)
List<MyObject> orderedList = unorderedList.OrderBy(p => p.Details.Find(s => s.Name == sortColumn).Value).ToList();
Is there a way to convert the values in the predicate to do this? Any help appreciated!
Rather gross and inefficient:
List<MyObject> orderedList = unorderedList.OrderBy(p => DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value)).ToList();
To reduce the number of lookups/parsing:
List<MyObject> orderedList =
(from extracted in (from p in unorderedList
select new { Item = p, Date = DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value })
orderby extracted.Date
select extracted.Item)
.ToList();
Project the date/time value and then sort by it.
var orderedList =
(from p in unorderedList
let value = DateTime.Parse(p.Details.Find(s => s.Name == sortColumn).Value)
orderby value
select p)
.ToList();