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...
Related
How can I search based on relevance to flutter? I'm not just talking about displaying the searched data. I am talking about the ones closest to the term to be searched in terms of their letters to the top. Normally the index order with listviewbuilder is 1,2,3 ... normally. But if the search term is closest to the word having the 2nd id among the data, I want the order to change to 2, 1, 3. How can I achieve this?
the codes I tried
_dataResults = _dataList.where((a) {
return (a.data_name.contains(controller.text) ||
a.data_name.toLowerCase().contains(controller.text) ||
a.data_name.toUpperCase().contains(controller.text) ||
a.data_name.startsWith(controller.text) ||
a.data_name.endsWith(controller.text) ||
a.data_title.contains(controller.text) ||
a.data_title.toLowerCase().contains(controller.text) ||
a.data_title.startsWith(controller.text) ||
a.data_title.endsWith(controller.text) ||
a.data_description.contains(controller.text) ||
a.data_description.toLowerCase().contains(controller.text) ||
a.data_description.startsWith(controller.text) ||
a.data_description.endsWith(controller.text));
}).toList();
In drool we have any option to find what all condition tuples satisfied in a rule, when I execute a stateless session with fact.
ex: if we have rule condition in a rule RUL1,
car.schi == 'A' || car.carKind str[startsWith] 'A'
if RUL1 is satisfied because of car.schi, then do we have any API where I can get this info(car.schi).
The example what I given was simpler but our actual business rule was so complex as shown below,
(car.carKind != \"EZZ\" && car.carKind != \"ENG\" && car.carKind != \"ETD\") && ((car.schi contains \"N1\" || car.schi contains \"N2\") || ((car.schi contains \"IH\" || car.schi contains \"N4\" || car.schi contains \"OM\" || car.schi contains \"DA\" || car.schi contains \"N5\" || car.schi contains \"PA\" || car.schi contains \"FG\" || car.schi contains \"PL\" || car.schi contains \"PC\" || car.schi contains \"PO\" || car.schi contains \"NG\" || car.schi contains \"OX\" || car.schi contains \"OP\" || car.schi contains \"NS\" || car.schi contains \"FS\" || car.schi contains \"FL\" || car.schi contains \"N3\" || car.schi contains \"CM\" || car.schi contains \"DW\" || car.schi contains \"PB\") && (validateElementRule($trainrulesRequestDTO.getElementRuleMap(),\"1_N\",true,$trainrulesRequestDTO.getCar().getCarNumb())))) && (((car.prevSchi not contains \"N2\" && car.prevSchi not contains \"N1\") && (car.prevLoadEmpty == \"L\") && ((car.prevCarKind str[startsWith] \"F\" || car.prevCarKind str[startsWith] \"YF\") && (car.prevCarKind not str[startsWith] \"FI\" && car.prevCarKind not str[startsWith] \"FA\" && car.prevCarKind not str[startsWith] \"FW\" && car.prevCarKind not str[startsWith] \"FB\") && (car.prevCarKind != \"YFB\"))) || ((car.nextSchi not contains \"N2\" && car.nextSchi not contains \"N1\") && (car.nextLoadEmpty == \"L\") && ((car.nextCarKind str[startsWith] \"F\" || car.nextCarKind str[startsWith] \"YF\") && (car.nextCarKind not str[startsWith] \"FA\" && car.nextCarKind not str[startsWith] \"FB\" && car.nextCarKind not str[startsWith] \"FI\" && car.nextCarKind not str[startsWith] \"FW\") && (car.nextCarKind != \"Y\" || car.nextCarKind != \"YFB\"))))
If we are to split it as different rules to find if the rule was satisfied because of( prevCarKind , prevSchi , prevLoadEmpty) or (nextCarKind, nextSchi,nextLoadEmpty) it would be too hard to split the complex rule.
I have also given the rule condition as image took from our UI application.
Pictorial view of above rule condition string
Would be helpful if someone can let us know on how to find if the above is satisfied based on which condition.
Regards,
Madhankumar. B
Thanks,
Madhan
No you can't. But you could split the rule into multiple rules like this:
rule "RUL1A"
when
car.schi == 'A'
then
...
end
rule "RUL1B"
when
car.carKind[0] == 'A'
then
...
end
You could split your condtion into several functions (and define them in drl):
function boolean isKindEzzEngEtd(Car car) {
return car.carKind in ["EZZ", "ENG", "ETD"];
}
function boolean isSchiContainsN1N2(Car car) {
return (car.schi contains "N1" || car.schi contains "N2");
}
...
then use the functions inside your rules (it also improves readablility and re-use):
rule "RUL1"
when
$car: Car()
!isKindEzzEngEtd($car) || isSchiContainsN1N2($car) && ...
then
-- call the functions one by one to find out which one returned true:
System.out.println("NOT isKindEzzEngEtd: " + !isKindEzzEngEtd($car));
System.out.println("isSchiContainsN1N2: " + isSchiContainsN1N2($car));
end
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)
Doing a simple Squeryl database lookup, but trying to exclude a value. I've tried:
j.id not jobExclude and j.id != jobExclude
however the first triggers a compiler error and the second triggers a runtime error.
The whole transaction:
from(DB.jobs)(j =>
where((j.startTime >= todayStart)
and (j.startTime <= todayEnd)
and (j.userId === userId)
and (j.teamId === teamId)
and (j.startOrder >= index)
and (j.id not jobExclude))
select (j)).toList
Thanks!
Courtesy of the Squeryl Groups:
Not equals is <>
so in the bigger picture:
(job.id <> jobExclude)
See http://squeryl.org/functions.html
Credit https://groups.google.com/forum/?fromgroups#!topic/squeryl/Hw7iVyvLLNM
I'm using Drools (for the first time) to express some rules and it has been working really well so far. However I've been given a new condition that I'm not able to express in the rules language very clearly.
Essentially I need to perform an action on the players account if they have an outstanding balance on there account between a certain amount, where they haven't made a payment in the last week and where they haven't made a payment in the last 4 weeks that is greater than or equal to a weekly deduction. There are a few other rules but I've removed them in an effort to simplify the rule for this question. It's the last rule that is causing me a problem.
rule "The broken rule"
salience 10
no-loop
when
Player( $playerNumber : playerNumber )
$a : Account( // balance between £5 and £100 and no arrangement
playerNumber == $playerNumber &&
accountBalanceInPence >= 500 &&
accountBalanceInPence <= 10000
)
not ( // no payment in last week
exists AccountTransaction(
playerNumber == $playerNumber &&
transactionDate >= oneWeekAgo &&
transactionCode == "P" // payment
)
)
/* It's this next bit that is broken */
not ( // no payment > (weekly cost * 4) paid within last 4 weeks
$deduction : AccountTransaction( // a recent transaction
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "D" // deduction
)
exists AccountTransaction( // the payment
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "P" // payment
amountInPence >= ($deduction->amountInPence * 4)
)
)
then
// do some action to the account
end
The problem is that it just doesn't work, I keep getting org.drools.rule.InvalidRulePackage exceptions thrown. I was just guessing on the syntax but couldn't seem to find an example that showed what I'm trying to do. Is it even possible?
The full original error message is:
"unknown:50:3 mismatched token: [#255,1690:1695='exists',<39>,50:3]; expecting type RIGHT_PAREN[54,4]: unknown:54:4 mismatched token: [#284,1840:1852='amountInPence',<7>,54:4]; expecting type RIGHT_PAREN[54,22]: unknown:54:22 Unexpected token '$payment'"
After trying the suggestion in the first comment the error is:
"[50,3]: unknown:50:3 mismatched token: [#255,1690:1695='exists',<39>,50:3]; expecting type RIGHT_PAREN[54,4]: unknown:54:4 mismatched token: [#284,1840:1852='amountInPence',<7>,54:4]; expecting type RIGHT_PAREN[54,45]: unknown:54:45 mismatched token: [#293,1881:1881='*',<71>,54:45]; expecting type LEFT_PAREN[55,3]: unknown:55:3 mismatched token: [#298,1890:1890=')',<12>,55:3]; expecting type THEN"
yes as you guessed, you need to put an explicit "and" inside the "not" pattern to join them together.
The only time you don't need the "and" is at the top level:
eg
when Foo() Bar()
Doesn't require a an "and"
but this is implicitly the same as
when Foo() and Bar()
So your solution seems correct. The lack of a top level "and" seems to be convention in most rule languages (going back to CLIPS !)
After some more hacking around the following doesn't cause any runtime errors (though I'm not sure if it's "correct" yet). I rewrote the clause to put the exists around both the facts and used an infix and to group them.
not ( // no payment > (weekly cost * 4) paid within last 4 weeks
exists (
AccountTransaction( // a recent transaction
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "D" // deduction
$recentDeducation : amountInPence
) and
AccountTransaction( // the payment
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "P" // payment
amountInPence >= ($recentDeducation * 4)
)
)
)
Thanks for all the help so far.
What about ($deduction->amountInPence * 4)? I think, the -> should be a . instead.