Is there a better way of shortening this LINQ statement? - c#

var filteredItemNumber = 0;
if (!string.IsNullOrEmpty(searchTerm))
{
filteredItemNumber =
this._objectsRep.Find(
r =>
r.ObjectTitle.StartsWith(searchTerm) && r.CreatedDate >= timePeriod.Start
&& r.CreatedDate <= timePeriod.End).Count();
}
else
{
filteredItemNumber =
this._objectsRep.Find(t => t.CreatedDate >= timePeriod.Start && t.CreatedDate <= timePeriod.End)
.Count();
}
I am sure there must be a shorten way to get rid of the if statement but I cannot figure it out how. when I use the following code the filtering returns different result than what I am expecting. Maybe the parentheses are not in right place ?
this._objectsRep.Find(r =>
searchTerm == null || r.ObjectTitle.StartsWith(searchTerm) && r.CreatedDate >= timePeriod.Start
&& r.CreatedDate <= timePeriod.End).Count()
What I am trying to achieve is that if the serchTerm is empty or null just ignore that filter but use the date range only.
Thanks

You don't need List.Find which returns a new list, you can use LINQ to count:
int filteredItemNumber = _objectsRep.Count(r =>
(string.IsNullOrEmpty(searchTerm) || r.ObjectTitle.StartsWith(searchTerm))
&& r.CreatedDate >= timePeriod.Start
&& r.CreatedDate <= timePeriod.End);

I think you just need to wrap the searchTerm condition like this:
this._objectsRep.Find(r =>
(string.IsNullOrEmpty(searchTerm) || r.ObjectTitle.StartsWith(searchTerm))
&& r.CreatedDate >= timePeriod.Start
&& r.CreatedDate <= timePeriod.End).Count()

filteredItemNumber =
this._objectsRep.Find(
r =>
r.ObjectTitle.StartsWith(searchTerm??"") && r.CreatedDate >= timePeriod.Start
&& r.CreatedDate <= timePeriod.End).Count();

Related

check if a date is null from within a lambda expression and use an alternative date only if it is null

I have some code to search for records created between two input dates (from and to) based upon the createdDate, however we have just imported some old data and not all of the records have a createdDate which means that some records are not returned. My idea is that when there is no createdDate, I use the plannedStartDate instead. This is my original code:
mainTables = mainTables.Where(d =>
d.n.CreatedDate >= AdminSearchVm.AdminSearch.SubmittedFrom &&
d.n.CreatedDate <= AdminSearchVm.AdminSearch.SubmittedTo);
but I would like to do something like this:
mainTables = mainTables.Where(d =>
d.n.CreatedDate == null ? d.n.PlannedStartDate :
d.n.CreatedDate >=
AdminSearchVm.AdminSearch.SubmittedFrom && d.n.CreatedDate == null ?
d.n.PlannedStartDate :
d.n.CreatedDate <= AdminSearchVm.AdminSearch.SubmittedTo);
try this
mainTables = mainTables.Where(d =>
((d.n.CreatedDate == null && d.n.PlannedStartDate >= AdminSearchVm.AdminSearch.SubmittedFrom)
|| (d.n.CreatedDate != null && d.n.CreatedDate >= AdminSearchVm.AdminSearch.SubmittedFrom))
&& ((d.n.CreatedDate == null && d.n.PlannedStartDate <= AdminSearchVm.AdminSearch.SubmittedIo)
|| (d.n.CreatedDate != null && d.n.CreatedDate <= AdminSearchVm.AdminSearch.SubmittedIo)));
or you can like this
mainTables = mainTables.Where(d =>
(d.n.CreatedDate == null
&& d.n.PlannedStartDate >= AdminSearchVm.AdminSearch.SubmittedFrom
&& d.n.PlannedStartDate <= AdminSearchVm.AdminSearch.SubmittedTo)
||
(d.n.CreatedDate != null
&& d.n.CreatedDate >= AdminSearchVm.AdminSearch.SubmittedFrom
&& d.n.CreatedDate <= AdminSearchVm.AdminSearch.SubmittedIo));
Maybe you can use this approach:
mainTables = mainTables
.Select(t => new { Table = t, Date = (t.n.CreatedDate ?? t.n.PlannedStartDate) })
.Where(x => x.Date >= AdminSearchVm.AdminSearch.SubmittedFrom && x.Date <= AdminSearchVm.AdminSearch.SubmittedTo)
.Select(x => x.Table);

How to set date between AM/PM 24-hour

I have 2 parameters. one is defaultFromD and another is defaualtToD. if I give 2 date range for this x.CreatedOn >= defaultFromD && x.CreatedOn <= defaultToD
x.CreatedOn >= '2021-10-17' && x.CreatedOn <= '2021-10-20'
its working. but if I give same date for this two parameters this condition is not working.
x.CreatedOn >= '2021-10-20' && x.CreatedOn <= '2021-10-20'
I want to knw how to pass this 2 logic in one condition. Please help me to resolve this issue.
Thank you...
public ResponseDTO<IQueryable<LabRequestForLabOrderDTO>> GetApprovedLabRequestsQueryable(DateTime defaultFromD, DateTime defaultToD)
{
var resp = ResponseBuilder.Build<IQueryable<LabRequestForLabOrderDTO>>();
var reqs = this.labRequestRepository.GetAllActive().Where(x => x.IsActive && x.TrxStatus == 1 && x.InvoiceStatus == "Approved"
&& x.CreatedOn >= defaultFromD && x.CreatedOn <= defaultToD)
.Select(x => new LabRequestForLabOrderDTO
{
Clinic = x.Clinic,
LabOrderCreated = x.LabOrderCreated,
InvoiceStatus = x.InvoiceStatus,
CreatedOn = x.CreatedOn
}).AsQueryable();
resp.AddSuccessResult(reqs);
return resp;
}
Try this
x.CreatedOn.AddDays(-1) > defaultFromD && x.CreatedOn.AddDays(1) < defaultToD
This is due to DateTime and Date Formate.
You should try the following way.
Consider you column CreatedOn datatype is: DateTime
x.CreatedOn.Date >= '2021-10-20' && x.CreatedOn.Date <= '2021-10-20'
This work for me
var todate = defaultToD.AddDays(1);
x.CreatedOn >= defaultFromD && x.CreatedOn <= todate

wrong expression result linq

I want to get records with parentIds. But this Linq expression gave me elements with 0 parentId value.
var orders =
OrderEquityTransactions.AsParallel().Where(
o => o.FinancialInstrumentId == financialInstrumentPrice.FinancialInstrumentId &&
o.ParentId != 0 &&
o.DebitCredit == "A" ? o.Price >= financialInstrumentPrice.Price : o.Price <= financialInstrumentPrice.Price).ToList();
After some digging I rewrote expression with additional two brackets and problem solved.
var orders =
OrderEquityTransactions.AsParallel().Where(
o => o.FinancialInstrumentId == financialInstrumentPrice.FinancialInstrumentId &&
o.ParentId != 0 &&
(o.DebitCredit == "A" ? o.Price >= financialInstrumentPrice.Price : o.Price <= financialInstrumentPrice.Price)).ToList();
What is the reason of this behavior?
Because in the first case it was interpreted as:
o => (o.FinancialInstrumentId == financialInstrumentPrice.FinancialInstrumentId
&& o.ParentId != 0 && o.DebitCredit == "A")
? o.Price >= financialInstrumentPrice.Price
: o.Price <= financialInstrumentPrice.Price
which is absolutely another.
Please, read this article on operator precedence.
Ternary conditional operator has the lower priority than conditional AND.
As per Operator precedence and associativity, conditional ANDs have a higher precedence than the conditional operator. So C# evaluates your expresion like this:
(o.FinancialInstrumentId == financialInstrumentPrice.FinancialInstrumentId
&& o.ParentId != 0 && o.DebitCredit == "A")
? o.Price >= financialInstrumentPrice.Price
: o.Price <= financialInstrumentPrice.Price

How to use DATEADD over column in LINQ - DateAdd is not recognized by LINQ

I am trying to invalidate requests of friendship that were reponded less than 30 days ago.
var requestIgnored = context.Request
.Where(c => c.IdRequest == result.IdRequest
&& c.IdRequestTypes == 1
&& c.Accepted == false
&& DateTime.Now <= (((DateTime)c.DateResponse).AddDays(30)))
.SingleOrDefault();
c.DateResponse is of type DateTime?. The error I am having is :
LINQ does not recognize the command .AddDays
Edit: If you're using EntityFramework >= 6.0, use DbFunctions.AddDays. For older versions of Entity Framework, use EntityFunctions.AddDays:
var requestIgnored = context.Request
.Where(c => c.IdRequest == result.IdRequest
&& c.IdRequestTypes == 1
&& c.Accepted == false
&& DateTime.Now <= DbFunctions.AddDays(c.DateResponse, 30))
.SingleOrDefault();
You might try this:
var thirtyDaysAgo = DateTime.Now.AddDays(-30);
var requestIgnored = context.Request
.Where(c =>
c.IdRequest == result.IdRequest &&
c.IdRequestTypes == 1 &&
c.Accepted == false &&
c.DateResponse.HasValue &&
thirtyDaysAgo <= c.DateResponse.Value)
.SingleOrDefault();

Linq and work with Datetime?

I need to do this :
context.Ads.Where(c => c.PublishedDate.HasValue &&
c.EndDate.HasValue &&
c.EndDate.Value.AddTicks(c.PublishedDate.Value.Ticks) > currentTime &&
c.AdStatusMail.Where(b => b.StatusKey != (int)AdStatusMailKey.EndedRemainder && b.StatusKey != (int)AdStatusMailKey.MiddleRemainder).Count() < 1)
.ToList();
The problem is that AddTicks can´t be used in Linq. I have looked at the EntityFunctions but can´t see how to use it to do what I need?
IQueryable can't handle the ticks, make it IEnumerable (or tolist). Here is an example:
context.Ads.Where(c => c.PublishedDate.HasValue && c.EndDate.HasValue && c.AdStatusMail.Where(b => b.StatusKey != (int)AdStatusMailKey.EndedRemainder && b.StatusKey != (int)AdStatusMailKey.MiddleRemainder).Count() < 1)
.AsEnumerable()
.Where (c => c.EndDate.Value.AddTicks(c.PublishedDate.Value.Ticks) > currentTime)
.ToList();

Categories

Resources