I want to select data from SQL database using EF, select the last hour and then group by minute.
var result = _dbContext.views
.Where(x => x.Id == id && x.Created > DateTime.UtcNow.AddHours(-1))
.OrderBy(x => x.Created)
.GroupBy(x=> x.Created.Where({Range is 1 minute}));
DateTime instance has a Minute property which is an int so you can use the x.Created.Minute for grouping:
var result = _dbContext.views
.Where(x => x.Id == id && x.Created > DateTime.UtcNow.AddHours(-1))
.OrderBy(x => x.Created)
.GroupBy(x=> x.Created.Minute}));
Related
I have a query like so:
if (catId == null || catId == 0)
{
productVM = db.Products
.Include(x => x.Category)
.ToArray()
.Select(x => new ProductVM(x))
.ToList();
}
else
{
productVM = db.Products
.Include(x => x.Category)
.ToArray()
.Where(x => x.CategoryId == catId)
.Select(x => new ProductVM(x))
.ToList();
}
That works, but as you can see the only difference between the 2 queries is .Where(x => x.CategoryId == catId).
Is there a more elegant way to write this?
Entity Framework doesn't actually query the database until you materialise the data, for example with ToList() or iterating over the results. So you can build up your query as you go without hitting the database:
var query = db.Products.Include(x => x.Category);
if(catId != null && catId != 0)
{
//Add a where clause
query = query.Where(x => x.CategoryId == catId);
}
productVM = query
.ToList()
.Select(x => new ProductVM(x));
Note that I removed the ToArray call as that also materialises the data which means each subsequent method on the data is acting on the entire table from the database.
You could expand the Where statement to include the test for null or 0 on catId. This might not work if the field catId in the database is nullable or can have a value of 0.
productVM = db.Products
.Include(x => x.Category)
.Where(x => catId == null || catId == 0 || x.CategoryId == catId)
.Select(x => new ProductVM(x))
.ToList();
Also you should remove the ToArray() as it queries the entire Products table from the database then perform the filtering and projecting in memory on the client.
Another way.
var products = db.Products.Include(x => x.Category).ToArray()
if (catId == null || catId == 0)
{
productVM = products.Select(x => new ProductVM(x)).ToList();
}
else
{
productVM = products.Where(x => x.CategoryId == catId)
.Select(x => new ProductVM(x)).ToList();
}
Simply re-assign query:
var query = db.Products;
if (condition)
query = query.Where(criteria);
var list = query.ToList();
Could you help me to improve this code?
var orderNo = "1234";
var maxValue = MyTable.Where(x => x.OrderNo == orderNo )
.OrderByDescending(x => x.Filename)
.Select(x => x.Filename)
.FirstOrDefault();
var list = (from x in MyTable
where x.OrderNo == orderNo && x.Filename == maxValue
select x).Distinct();
list.Dump();
Is it possible to improve these 2 Linq queries into 1 and avoiding query 2 times my database. Something like:
var list = (from x in MyTable
where x.OrderNo == orderNo && MaxValue(x.Filename)
select x)
.Distinct();
You could use GroupBy:
var list = MyTable
.Where(x => x.OrderNo == "1234") // or var1
.GroupBy(x => x.Filename)
.OrderByDescending(g => g.Key)
.First()
.Distinct();
Try
var list = (
from x in MyTable
where x.OrderNo == var1 &&
x.Filename == MyTable.Where(x => (x.OrderNo == "1234")).Max(p => p.Filename)
select x
).Distinct();
Why not just:
MyTable.Where(x => x.OrderNo == "1234")
.Max(x => x.Filename);
You will get all the records that have the maximal filename.
var TotalFee = (from item in _dbEntities.MonthlyFees
where item.Year == DateTime.Now.Year &&
item.FeeStatus == true
select item).GroupBy(x =>x.MonthID);//.AsEnumerable().Sum(x => int.Parse(x));
I want to sum Column "Fee" which is nvarchar type and group it by MonthID
Just look to this example
var feesDictionary = _dbEntities.MonthlyFees
.Where(x => x.Year.Equals(DateTime.Now.Year) && x.FeeStatus)
.GroupBy(x => x.MonthID)
.ToDictionary(x => x.Key, x => x.Sum(y => Convert.ToDouble(y.Fee)));
The keys are identifiers of months and values - sums of fee for appropriate month.
I am try to build a dictionary with a list of dates as values.
I am not sure what extension method that I need to use inorder to get to the solution. Tried doing a ToList() on the value field but its throwing an exception.
Below is the code that I am using.
GolfitoDataContext db = new GolfitoDataContext();
var dic = db.GetTable<History>()
.Select(p => new { p.Title, p.Date})
.Where(x => x.Date >= startDateFilter && x.Date <= endDateFilter)
.DistinctBy(x => x.Title)
.AsEnumerable()
.ToDictionary(k => k.Title, k => k.Date);
For example for the below data
Date Title
2013-07-18 22:51:45.000 QA
2013-07-18 22:52:30.000 Controller
2013-07-18 22:52:30.000 Controller
2013-07-18 22:58:00.000 Agent
2013-07-18 23:07:00.000 QA
2013-07-18 23:07:45.000 Controller
2013-07-18 23:08:30.000 Planning
I am trying to build a dictionary which will give me all the instances of individual titles(QA,Controller,etc.) and their occurrences (date on which the instances occurred). Basically building a Dictionary<string,List<DateTime>>
You should use GroupBy:
var dic = db.GetTable<History>()
.Select(p => new { p.Title, p.Date})
.Where(x => x.Date >= startDateFilter && x.Date <= endDateFilter)
.GroupBy(x => x.Title)
.ToDictionary(g => g.Key, g => g.Select(x => x.Date).ToList());
The ToLookup method encompasses that:
GolfitoDataContext db = new GolfitoDataContext();
var dic = db.GetTable<History>()
.Select(p => new { p.Title, p.Date})
.Where(x => x.Date >= startDateFilter && x.Date <= endDateFilter)
.ToLookup(k => k.Title, k => k.Date);
A lookup is basically the same as a multi-map, and can be used for example as:
foreach(var date in dic[title])
{
// ...
}
you need to build the list before you try to build the dictionary. You can do this by use of group by
var dic = (from x in db.GetTable<History>()
where x.Date >= startDateFilter && x.Date <= endDateFilter
group x.Date by x.Title)
.ToDictionary(grp => grp.Key, grp.ToList());
I have a sql query and would like to convert it into linq
SELECT CAST([Date] AS DATE),
COUNT([ID]) AS 'Amount of Systems'
FROM [DemoDB].[dbo].[Servers]
WHERE [ServerID] IN ('ServerX') AND [Type] = 'Complete'
GROUP BY CAST([Date] AS DATE)
ORDER BY CAST([Date] AS DATE)
this will return the result as follows
What I have tried
//fromDP and toDP are the names of the Datepicker's
var query = (this.db.Servers
.Where(x => x.Date >= fromDP.SelectedDate.Value &&
x.Date <= toDP.SelectedDate.Value));
var query_Success = query.Count(p => p.Type == "Complete"
&& (p.ServerID == "ServerX"));
and I have the result as Count on the whole ( for example, if I select from from April 1st to April 15th , the result is the sum of all "complete"), but I need count for each day in this selected range. the result I will bind to the column chart.
how to proceed ?
If I understood correctly the author wants to use only the date without the time. To do this with EF we can use the method EntityFunctions.TruncateTime for trimming the time portion. I will build on #steaks answer:
db.Servers.Where(s => s.ServerId == "ServerX" && s.Type == "Complete")
.GroupBy(s => EntityFunctions.TruncateTime(s.Date))
.OrderBy(s => s.Key)
.Select(g => new {Date = g.Key, AmountOfSystems = g.Count()});
this.db.Servers.Where(s => s.ServerId == "ServerX" && s.Type == "Complete")
.GroupBy(s => s.Date)
.OrderBy(s => s.Key)
.Select(g => new { Date = g.Key, AmountOfSystems = g.Count() });
Change the Where clause to read
Where(s => s.ServerId == "ServerX" && s.Type == "Complete" && s.Date >= fromDP.SelectedDate.Value && s.Date <= toDP.SelectedDate.Value)
to filter to a limited date range.
EDIT
As #vvs0205 suggested. Use EntityFunctions class to manipulate the date column as you please: http://msdn.microsoft.com/en-us/library/system.data.objects.entityfunctions.aspx
Something like this
var fromDate = fromDP.SelectedDate.Value;
var toDate= toDP.SelectedDate.Value;
var q = from server in this.db.Servers
where (server.Date >= fromDate && server.Date<=toDate && server.ServerID="ServerX" && server.Type=="Complete")
group server by server.Date
into g
orderby g.Key
select new
{
Date = g.Key,
Count = g.Count()
};
var results = q.ToList();