问题
I want Linq to group by date but display in text
here is my code
var groups = _uow.Orders.GetAll()
.Where(x => x.Created > baselineDate)
.GroupBy(x => x.Created.ToString("yyyy-MM-dd"));
var orders = new
{
Day = groups.Select(g => g.Key).ToArray(),
Total = groups.Select(g => g.Sum(t => t.Total)).ToArray(),
};
the result is (not good to put in label of graph)
{"Day": [2, 3, 4, 5], "Total": [9999.00, 9999.00, 9999.00, 9999.00] }
But i want this (Monthly)
"Day": ['Jan', Feb', 'Mar', 'Apr'], "Total": [9999.00, 9999.00, 9999.00, 9999.00] }
Or Daily
"Day": ['Jan 1', 'Jan 2', 'Jan 3', 'Jan 4'], "Total": [9999.00, 9999.00, 9999.00, 9999.00] }
Please advice me for DateTime.ToString() that i can play with.
Thank you all.
回答1:
Thank you all for helping. I found the answer.
add
.AsEnumerable()
AND
.GroupBy(x => x.Created.ToString("MMM d"));
here is full code
var groups = _uow.Orders.GetAll()
.Where(x => x.Created > baselineDate)
.AsEnumerable()
.GroupBy(x => x.Created.ToString("MMM d"));
var orders = new
{
Day = groups.Select(g => g.Key).ToArray(),
Total = groups.Select(g => g.Sum(t => t.Total)).ToArray(),
};
回答2:
This question describes how to convert a date time to the string name of the month.
EDIT: for EF, we have to pull everything into memory before doing any string logic:
var orders = _uow.Orders.GetAll()
.Where(x => x.Created > baselineDate)
// pull into memory here, since we won't be making the result set any smaller and
// we want to use DateTime.ToString(), which EF won't compile to SQL
.AsEnumerable()
// this will group by the whole date. If you only want to group by part of the date,
// (e. g. day or day, month), you could group by x => x.Date.Month or the like
.GroupBy(x => x.Date)
.Select(g => new {
// or use just "MMM" for just the month
Dates = g.Select(g => g.Key.ToString("MMM d")).ToArray(),
Total = ...
});
回答3:
You need to use functions that EF can understand and translate to SQL, such as EntityFunctions.TruncateTime. Here is your updated code:
var groups = _uow.Orders.GetAll()
.Where(x => x.Created > baselineDate)
.GroupBy(x => EntityFunctions.TruncateTime(x.Created));
Then use the string formatting just in the output, but make sure you're doing it after the value has been returned to .Net, using AsEnumerable
to switch to Linq-to-Objects:
var orders = new
{
Day = groups.Select(g => g.Key)
.AsEnumerable()
.Select(x => x.ToString("MMM d"))
.ToArray(),
Total = groups.Select(g => g.Sum(t => t.Total)).ToArray(),
};
来源:https://stackoverflow.com/questions/17476542/linq-group-by-and-then-display-datetime-for-dd-mmm