Get result from multiple where conditional statements in LINQ - c#

I am trying to get the result based upon the values of variables temp_DestinationGroupName, temp_CountryName and temp_RateTypeId.
If any of these variables are null or 0, it should not be included in where clause and rest statements should work and bring the result. I am getting zero rows using this query. Kindly suggest me something with these conditions in where clause. i tried following solutions on stackoverflow but still not getting the desired result.
var Rows = _CustomerRatesList.Where(w => (w.Id != rates.Id)
&& (w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
&& (w.CountryName == temp_CountryName || temp_CountryName!=null)
&& (w.RateTypeId == temp_RateTypeId || temp_RateTypeId !=0));

(w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
Your condition here will return true as long as your input variable temp_DestinationGroupName is not null. I don't think that's what you had in mind.

You can split in many Where to make your request more readable :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName != temp_DestinationGroupName || temp_DestinationGroupName != null)
.Where(w => w.CountryName != temp_CountryName || temp_CountryName != null)
.Where(w => w.RateTypeId != temp_RateTypeId || temp_RateTypeId !=0);
Notice that you must use != in first conditioon of all Where, so you'll get all data except when it's null. In your logic, may be the conditions will be == :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId ==0);
Each Where result is an IEnumerable, Rows will be a IEnumerable. If you want a List, just add .ToList()

I got the solution to this problem, now i am getting filtered result.
Thank you all for your time :)
var otherRows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId == 0);

Related

Linq Lambda Expressin Where Conditions And Performance Problem

I created where conditions with linq lambda expression for reporting. My conditions are running very slowly or it is throwing error.
Error Detail: Evoluation timed out.
How can i find correct query?
My codes:
var query = Worker.Members
.Where(u => string.IsNullOrEmpty(model.TcNumber) || u.TcNumber.Contains(model.TcNumber))
.Where(u => string.IsNullOrEmpty(model.FullName) || u.FullName.Contains(model.FullName))
.Where(u => model.BirthYear == null || u.BirthDate.Year >= model.BirthYear)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.GenderId == null || u.GenderId == model.GenderId)
.Where(u => model.DistrictCode == null || u.Contacts.Any(c => c.DistrictCode == model.DistrictCode && c.IsActive))
.Where(u => model.StreetCode == null || u.Contacts.Any(c => c.StreetCode == model.StreetCode && c.IsActive))
.Where(u => model.ExteriorDoor == null || u.Contacts.Any(c => c.ExteriorDoor == model.ExteriorDoor && c.IsActive))
.Where(u => model.InteriorDoor == null || u.Contacts.Any(c => c.InteriorDoor == model.InteriorDoor && c.IsActive))
.Where(u => model.DisabledGroupId == null || u.Disableds.Any(d => d.ReportDisabledGroups.Any(c => c.DisabledGroupId == model.DisabledGroupId)))
.Where(u => model.ContributionTypeId == null || u.Demands.Any(d => d.ContributionTypeId == model.ContributionTypeId && !d.IsDeleted))
.Where(u => model.DemandStatusId == null || u.Demands.Any(d => d.DemandStatusId == model.DemandStatusId && !d.IsDeleted))
.Where(u => model.DemandDateStart == null || u.Demands.Any(d => d.DemandDate >= model.DemandDateStart && !d.IsDeleted))
.Where(u => model.DemandDateEnd == null || u.Demands.Any(d => d.DemandDate <= model.DemandDateEnd && !d.IsDeleted))
.Where(u => u.IsTcCitizen == model.IsForeign)
.Where(u => u.IsDisabled == model.IsDisabled)
.Where(u => u.IsAlive == model.IsAlive);
The correct pattern (assuming Worker.Members is an IQueryable, not an IEnumerable) here is to conditionally add the criteria, like this:
var query = Worker.Members;
if (!string.IsNullOrEmpty(model.TcNumber))
query = query.Where(u => u.TcNumber.Contains(model.TcNumber));
if (!string.IsNullOrEmpty(model.FullName)
query = query.Where(u => u.FullName.Contains(model.FullName));
if (!model.BirthYear == null)
query = query.Where(u => u.BirthDate.Year >= model.BirthYear);
. . .
Did you check this?
Here detailed descriptions are given.

Linq To SQL, why the huge performance difference between two similar queries that are returning the same number of records

I have two queries, the first returns all "Open" records where the reply-by-date has not passed and the second returns all "Open Unviewed" records where the reply-by-date has not passed and the record has not been viewed by the user (no entry in table RfqVieweds). In this scenario the user has not viewed any of the 1000 records so all 1000 are returned. The second to last line in each query (right before "select new RfqDto()") is where the difference is between the two queries.
The first query takes about 45 seconds to return 1000 records. The second query takes about 4 seconds to return the same 1000 records. Why? How do I get the first query to run as fast as the second?
Query 1:
var groupQuery = Rfqs.Where(rfqs => rfqs.IsPrimaryEmail && (rfqs.Contract != "Upstream"))
.GroupBy(rfqs => new {rfqs.RFQ_RFISeqNum})
.Select(g => new {g.Key.RFQ_RFISeqNum, RfqId = g.Max(p => p.RfqId)});
var query = (from m in groupQuery
join t in Rfqs on new {m.RfqId} equals new {t.RfqId}
join s in RfqSupplementals on new {RfqSeqNumber = t.RFQ_RFISeqNum} equals new {s.RfqSeqNumber}
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
from rfqStarred in RfqUserStarreds.Where(rs => rs.RfqSeqNumber == t.RFQ_RFISeqNum && rs.SalesRep == salesrep).DefaultIfEmpty()
let rcn = RfqCommentNotifications.Where(r => r.RfqSequenceNum == t.RFQ_RFISeqNum && r.SalesRep == salesrep).Select(d => d.LastViewed).FirstOrDefault()
let ch = RfqsChangeHistories.Where(r => r.RfqRfiSeqNum == t.RFQ_RFISeqNum && chgHistList.Contains(r.Action)).OrderByDescending(r => r.Id).FirstOrDefault()
where (isRfqUser == false || ((t.assignedTo == salesrep || t.secndAssignedTo == salesrep || t.addlAssignedTo == salesrep)
|| (agencies.Contains(t.Agency) && (t.assignedTo == null || t.assignedTo.Trim() == string.Empty)
&& (t.secndAssignedTo == null || t.secndAssignedTo.Trim() == string.Empty) && (t.addlAssignedTo == null || t.addlAssignedTo.Trim() == string.Empty))))
&& (!isRfqUser || t.HouseOpportunity == false)
&& t.IsDeleted == false && t.IsPrimaryEmail
&& (t.ReplyByDate > now || (t.ReplyByDate == null && t.IsManualRfq))
select new RfqDto()
Query 2:
var groupQuery = Rfqs.Where(rfqs => rfqs.IsPrimaryEmail && (rfqs.Contract != "Upstream"))
.GroupBy(rfqs => new {rfqs.RFQ_RFISeqNum})
.Select(g => new {g.Key.RFQ_RFISeqNum, RfqId = g.Max(p => p.RfqId)});
var query = (from m in groupQuery
join t in Rfqs on new {m.RfqId} equals new {t.RfqId}
join s in RfqSupplementals on new {RfqSeqNumber = t.RFQ_RFISeqNum} equals new {s.RfqSeqNumber}
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
from rfqStarred in RfqUserStarreds.Where(rs => rs.RfqSeqNumber == t.RFQ_RFISeqNum && rs.SalesRep == salesrep).DefaultIfEmpty()
let rcn = RfqCommentNotifications.Where(r => r.RfqSequenceNum == t.RFQ_RFISeqNum && r.SalesRep == salesrep).Select(d => d.LastViewed).FirstOrDefault()
let ch = RfqsChangeHistories.Where(r => r.RfqRfiSeqNum == t.RFQ_RFISeqNum && chgHistList.Contains(r.Action)).OrderByDescending(r => r.Id).FirstOrDefault()
where (isRfqUser == false || ((t.assignedTo == salesrep || t.secndAssignedTo == salesrep || t.addlAssignedTo == salesrep)
|| (agencies.Contains(t.Agency) && (t.assignedTo == null || t.assignedTo.Trim() == string.Empty)
&& (t.secndAssignedTo == null || t.secndAssignedTo.Trim() == string.Empty) && (t.addlAssignedTo == null || t.addlAssignedTo.Trim() == string.Empty))))
&& (!isRfqUser || t.HouseOpportunity == false)
&& t.IsDeleted == false && t.IsPrimaryEmail
&& (rfqViewed == null && (t.ReplyByDate > now || (t.ReplyByDate == null && t.IsManualRfq)))
select new RfqDto()
You probably need to look at the query plan to see the true reason for the timing difference, as it depends on the actual data.
The two queries are different and if they happen to return the same number of rows, then Sql will have no way of knowing that in advance.
I can give you an example of one circumstance which could cause the difference.
First of all, lets simplify the query to
var query = (from m in groupQuery
join t in Rfqs on new { m.RfqId } equals new { t.RfqId }
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
where
t.ReplyByDate > now
select new RfqDto()
Now suppose you have 1 million rows in Rfqs and only 1000 records have a ReplyByDate values in the future. If ReplyByDate is not indexed, then that means that sql has to read and check all million rows before returning the selected 1000 rows.
But if the query becomes
var query = (from m in groupQuery
join t in Rfqs on new { m.RfqId } equals new { t.RfqId }
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
where
(t.ReplyByDate > now
&& rfqViewed == null
select new RfqDto()
and if it happens that there are only 10000 rows in Rfqs that do not have a record in RfqVieweds, and if rfqViewed has a suitable index that Sql can determine this quickly, then that means that Sql will only need to look at these 10000 records, which may be faster.
Note, If there are any rows with ReplyDates in the future that have been reviewed, then the two queries will not return the same records.

What is the best way to search data on multiple fields [duplicate]

This question already has answers here:
Dynamic where clause (OR) in Linq to Entities
(2 answers)
Closed 5 years ago.
I am working in ASP.NET MVC, I have a scenario where user can select multiple options to get list of doctors, this is how my action looks like.
public JsonResult DoctorsList(int? specialization , int? city, int? area, int? insurance_company, string doctor_name )
Any of these arguments can have some value and any number of them can be null also all of can be null in that I will return all the records.
Now I know a long and complicated way where I can make different combinations of these arguments and check which one is null and which one is not and then write my query based on that.
But is there any other shorter more efficient way?
Right now I am using OR conditions to get records like this
var doctors = db.Doctors.Where(e =>
e.specialization == specialization ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin=>sin.company_id).ToList().Contains(insurance_company) ||
e.first_name == doctor_name ||
e.last_name == doctor_name
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
But I want it to work in combinations, For Example Selecting Doctors with specialization_id = 1 and city_id=2 , of other combinations like this. But OR condition will be true if only one condition matches
For your scenario i think this approach might work rather than going around if else conditions. And i think && should be used to filter out exactly but you could use || operator if thats what you want,
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) &&
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) &&
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) &&
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) &&
(doctor_name != "" && e.first_name == doctor_name || e.last_name == doctor_name)
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
This is what I was looking for #imanshu15 answer gave me a hint.
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) || (specialization == null)
).Where(e =>
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) || (city == null)
).Where(e =>
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) || (area == null)
).Where(e =>
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) || (insurance_company == null)
).Where(e =>
(doctor_name != null && e.first_name == doctor_name) || (doctor_name == null)
)

Multiple using of || and && operands

I have a query using Entity Framework. It has many different operands and I am confused with its priority. I am getting the wrong result. I need all records that IsPaid == true or IsPaid == null, also all records must be TypeId == 1 or TypeId == 2, also must be CityId == 1 and CategoryId == 2. For some reason it doesn't evaluate CityId and CategoryId.
What am I doing wrong? Thanks.
var list = db.Ads.Where (x =>
x.IsPaid == true || x.IsPaid == null &&
x.TypeId == 1 || x.TypeId == 2 &&
x.CityId == 1 && x.CategoryId == 2
).ToList();
The best way to solve this problem is using brackets.
You should always use them even if you know the binding prioritys, to increase readability of your code.
(x.IsPaid == true || x.IsPaid == null) && (x.TypeId == 1 || x.TypeId == 2) && x.CityId == 1 && x.CategoryId == 2
&& has a higher proirity than ||
So false && false || true would be translated to (false && false) || true => true
Sidenote as mentioned by #Joey:
Instead of (x.IsPaid == true || x.IsPaid == null) you can write (x.IsPaid != false).
Due to operator precedence, && binds higher than ||.
If you chain Where statements, it's more clear what happens:
var list = db.Ads
.Where(x => x.IsPaid == true || x.IsPaid == null)
.Where(x=> x.TypeId == 1 || x.TypeId == 2)
.Where(x=> x.CityId == 1)
.Where(x=> x.CategoryId == 2)
.ToList();
&& has a higher precedence than ||, just like in math. So, effectively your condition is the following:
x.IsPaid == true ||
x.IsPaid == null && x.TypeId == 1 ||
x.TypeId == 2 && x.CityId == 1 && x.CategoryId == 2
If any of those expressions on separate lines are true, the whole expression is true. You have to use parentheses to clarify here:
(x.IsPaid == true || x.IsPaid == null) &&
(x.TypeId == 1 || x.TypeId == 2) &&
x.CityId == 1 &&
x.CategoryId == 2
Try this:
var list = db.Ads.Where (
(x => x.IsPaid == true || x.IsPaid == null) &&
(x.TypeId == 1 || x.TypeId == 2) &&
(x.CityId == 1 && x.CategoryId == 2)
).ToList();

How can I write the following lambda expression in one line?

I want to fetch the records as follows
SearchResult.condition is null then fetch all the rows from Person
if SearchResult.condition is false then fetch the rows where PersonType column contains null value
if SearchResult.condition is true then fetch the rows where PersonType column contains non null value
struct SearchResult
{
public string Name;
public bool? condition;
}
Expression<Func<Person, bool>> expression;
if(condition==null)
{
expression= (a =>
(SearchResult.Name==null || a.Name == SearchResult.Name)
);
}
else if(condition.Value == true)
{
expression= (a =>
(SearchResult.Name==null || a.Name == SearchResult.Name)
&& a.PersonType != null)
}
else if(condition.Value == false)
{
expression= (a =>
(SearchResult.Name==null || a.Name == SearchResult.Name)
&& a.PersonType == null)
}
I want to write the expression in one expression instead of using if else conditions. Can u plz help me in it?
Well you can do it with a conditional operator, but you need to specify the type of the expression tree for each lambda expression:
var expression = condition == null
? (Expression<Func<Person, bool>>) a => SearchResult.Name == null ||
a.Name == SearchResult.Name
: condition.Value
? (Expression<Func<Person, bool>>) a => (SearchResult.Name == null ||
a.Name == SearchResult.Name) &&
a.PersonType != null
: (Expression<Func<Person, bool>>) a => (SearchResult.Name == null ||
a.Name == SearchResult.Name) &&
a.PersonType == null;
But assuming you're going to use this with a LINQ query, you'd be much better off with something like:
var query = foo.Where(a => SearchResult.Name == null ||
a.Name == SearchResult.Name);
if (condition != null)
{
query = condition.Value ? query.Where(a => a.PersonType != null)
: query.Where(a => a.PersonType == null);
}
As an aside, I'd strongly advise you to avoid writing mutable structs or using public fields.
You could shorten as:
expression = a =>
(SearchResult.Name == null || a.Name == SearchResult.Name) &&
(SearchResult.condition == null || Search.condition == (a.PersonType != null));

Categories

Resources