EF 4.4 freeze on large table query - entity-framework

I m using EF 4.4 on ASP.NET MVC project with SQL server and my below query freeze every run.
PSSAL has 426.000 rows and PU_CustProduct has 1600 rows
Have any idea or offer for query?
var model = (from p in dbCont.PU_CustProduct
where !(from pt in dbCont.PSSAL
where pt.PSSAL_DATE > d1
&& pt.PSSAL_PSPRP_ID == p.CustProductID
select pt.PSSAL_PSPRP_ID).Contains(p.CustProductID)
&& p.IsActive == true
&& (!p.IsSleepMode == true)
&& p.ProductType == intId
&& p.CustomerID != null
&& p.IsSychSuspend != true
select new WarningViewModel
{
PrpName = p.LicenceName,
CrmID = p.CustomerID.ToString(),
PsprpId = p.CustProductID.ToString(),
}).Distinct().OrderBy(o => o.PrpName).ToList();

Related

Scala Quill: how to write? I need use GROUP BY and ORDER BY and multiple WHERE conditions

I want to get sql like this:
SELECT
v0.`uid`,
v0.`title`,
v0.`price`,
v0.`publishtime`,
v0.`status`,
v0.`type`,
v0.`is_lfst`,
v0.`app_image`
FROM
`news` v0
LEFT JOIN `news_zq` v1 ON v0.`id` = v1.`nid`
WHERE
v0.`status` = 1
AND v0.`is_lfst` = 1
AND v0.`type` = 2
AND v1.`zq_id` = 2
GROUP BY
v0.`id`
ORDER BY
v0.`publishtime` DESC
LIMIT 20 OFFSET 0
I tried "dynamicQuery" and "infix",but failed
dynamicQuery[News]
.leftJoin(dynamicQuery[NewsZq]).on((a, b) => a.id == b.nid)
.filter(_._1.status == lift(1))
.filterIf(newsDo.cid.isDefined && newsDo.cid.get > 0)(_._1.cid == lift(newsDo.cid.get))
.filterIf(newsDo.`type`.isDefined)(_._1.`type` == lift(newsDo.`type`.get))
.groupBy(_._1.id).map(_._2.map(_._1)) // error
.sortBy(_._1.publishtime)(Ord.desc)
.drop(quote(lift(offset)))
.take(quote(lift(limit)))
.map(_._1)

Filter by Age in EFCore using Postgresql - Npgsql

Is it possible to translate this following Postgresql query to EFCore?
SELECT "applic"."age" FROM (
SELECT EXTRACT(YEAR FROM age(birthdate)) :: int AS "age" FROM public.applicant
) AS "applic"
WHERE "applic"."age" < 50;
I've looked into the documents but I can't find anything helpful.
A solution that works:
var applicants = from s in this.RepositoryContext.Applicants select s;
if (query.AgeStart != null && query.AgeEnd != null)
{
applicants = applicants.Where(c => (DateTime.Today.Year - c.BirthDate.Year) >= query.AgeStart && (DateTime.Today.Year - c.BirthDate.Year) < query.AgeEnd);
}

Map SQL with JOIN, GROUP BY, and SUM to Entity Framework query

I'd like to map the following SQL to EF query. I found a few similar topics, but still failed to achieve the mapping. {0}...{2} are SQL parameters.
SELECT TaskGroup.Project AS Project
SUM(Datediff(minute, WorkLog.StartTime, WorkLog.EndTime)) / 60 AS Hours
FROM WorkLog INNER JOIN TaskDefinition ON WorkLog.TaskDefinitionID = TaskDefinition.ID
INNER JOIN TaskGroup ON TaskDefinition.TaskGroupID = TaskGroup.ID
WHERE WorkLog.EmployeeID = {0} AND WorkLog.Status = 5 AND
WorkLog.StartTime >= {1} AND WorkLog.EndTime < {2}
GROUP BY TaskGroup.Project
What about this?
var query = (from wl in WorkLog
join td in TaskDefinition on wl.TaskDefinitionID equals td.ID
join tg in TaskGroup on td.TaskGroupID equals tg.ID
where wl.EmployeeID == { 0} && wl.Status == 5
&& wl.StartTime >= { 1} && wl.EndTime < { 2}
select new
{
Project = tg.Project,
StartTime = wl.StartTime,
EndTime = wl.EndTime
})
.GroupBy(o => o.Project)
.Select(g => new
{
Project = g.Key,
Hours = g.Sum(o => (o.EndTime - o.StartTime).Minutes) / 60
});

Calculating Average Timespan between two dates in Entity Framework

I have a database table with two columns: StartDateTime and FinishDateTime. both are nullable datetime columns.
I'm wanting to calculate the Average time between both fields per row. ie the average duration of my recorded event.
I'm getting a "DbArithmeticExpression arguments must have a numeric common type."
Example EF code with a touch of simplification for the demo.
from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(p=> (p.FinishDateTime.Value - p.StartDateTime.Value).Ticks)
I'd love an example of the above, as SQL makes this a breeze.
Its depends on your data provider, it may support DbFunctions and you could do something like this:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(x=> DbFunctions.DiffMilliseconds(p.FinishDateTime,p.StartDateTime))
if it doesn't, i think you have to go linq to objects after the select:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.ToArray()
.Average(x=> (p.FinishDateTime -p.StartDateTime).Ticks)

Count before order, skip and take

I'm using Entity Framework together with Unit-of-work and repository pattern.
For a function with ordering, pagination, etc. I use the following code:
stammdatenEntityModels =
_unitOfWork.StammdatenRepository.Get()
.Where(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
))
.OrderBy(orderBy)
.Skip(inputModel.EntriesToDisplay*(inputModel.Page - 1))
.Take(inputModel.EntriesToDisplay)
.ToList();
Now I need to know the numbers of records, but before the skip and take (for pagination) is performed.
Therefore I have the same code again:
totalCount = _unitOfWork.StammdatenRepository.Get()
.Count(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
));
Unfortunately this leads to a lot of redundance and my query is performed twice. Is there any better solution?
I agree with the redundancy. What you can do is to cache the count result for the specific parameters (keyword, dateTime) a certain amount of time and use it again at subsequent calls to deliver paginated (skip, take) results from the StammDatenRepository.
This way you only have the overall count-call one time for specific parameters.
Found this SO question where a respected member states:
Thinking about it from a SQL point of view, I can't think of a way in
a single normal query to retrieve both the total count and a subset of
the data, so I don't think you will be able to do it in LINQ either.
So, I really think you have to cache some counts results to increase performance. You know best how to do it for your specific situation and if it's worth it at all...