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));
Related
I'm trying to do a conditional OrderBy but it's having no effect. The List outputs the same with default ordering.
I've tried both approaches suggested in this question Conditional "orderby" sort order in LINQ
var query = _context.Groups
.Where(gr => gr.Status != ((sbyte)ActiveStatus.DELETED)
&& gr.OrganisationId == user.OrganisationId
&& (search != null && gr.Name != null ? (gr.Name.Contains(search)) : true == true)
)
.Select(GroupReportModel.Projection);
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query.OrderByDescending(gr => gr.Name);
pager.TotalRecords = query.Count();
var list = query.Skip(pager.PageCount != null ? pager.PageCount.Value * (pager.Page.Value) : 0)
.Take(pager.PageCount != null ? pager.PageCount.Value : 0)
.ToList();
LINQ methods do not mutate the query object, they return a new one, you need to reassign it:
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query = query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query = query.OrderByDescending(gr => gr.Name);
....
public JsonResult SearchApplicantList(string SSession, string ApStatus, string StudyLevel, string SLPrograms)
{
ab db = new ab();
var SearchList = db.Students
.Where(x => x.SemesterSessioin == SSession
&& x.OverAllStatus == ApStatus
&& x.StudyLvl == StudyLevel
&& x.ProgPref1 == SLPrograms
&& x.ProgPref2 == SLPrograms
&& x.ProgPref3 == SLPrograms
&& x.progPref4 == SLPrograms).ToList();
return Json(SearchList, JsonRequestBehavior.AllowGet);
}
I want to get a list on the basis of parameters, but few cases the many parameters can be null, null means all.
How can I do this?
Programming. Step by step.
Let me explain:
There is no need to have only one line for the query.
var searchQuery = db.Students (possibly with .Where that is constant).
if (ApStatus != null) {
searchQuery = searchQuery.Where(x => x.OverAllStatus = ApStatus
}
Btw., plenty of spelling. It is App (not Ap) and Overall not OverAll - it is ONE word as per dictionary.
Anyhow, you can repeat adding where conditions as often as you want, then at the end materialize.
All where conditions are ANDed together.
This is one thing most people overlook - LINQ allows a TON of programming and manipulation of the query tree.
public JsonResult SearchApplicantList(string SSession, string ApStatus, string StudyLevel, string SLPrograms)
{
ab db = new ab();
var SearchList = db.Students;
SearchList = SearchList.Where(x => (x.SemesterSessioin == SSession || SSession ==null || SSession =="")
&& (x.OverAllStatus == ApStatus || ApStatus ==null || ApStatus =="")
&& (x.StudyLvl == StudyLevel || StudyLevel ==null || StudyLevel =="")
&& (x.ProgPref1 == SLPrograms || SLPrograms ==null || SLPrograms =="")
&& (x.ProgPref2 == SLPrograms || SLPrograms ==null || SLPrograms =="")
&& (x.ProgPref3 == SLPrograms || SLPrograms ==null || SLPrograms =="")
&& (x.progPref4 == SLPrograms|| SLPrograms == null|| SLPrograms == "").ToList();
return Json(SearchList, JsonRequestBehavior.AllowGet);
}
Apply filter by parameter/s which can not be null, for instance SSession and StudyLevel are those parameters which can not be null. So apply filter by them first
var SearchList = db.Students.Where(x => x.SemesterSessioin == SSession && x.StudyLvl == StudyLevel).ToList();
Then check rest of parameters one by one, for SLPrograms will be like:
if(!string.IsNullOrEmpty(SLPrograms))
{
SearchList = SearchList.Where(Apply Filter By SLPrograms).ToList();
}
And then for rest of Parameters. Remember, use if and if to check each parameters. Like
if(Param1)
{
//Code
}
if(Param2)
{
//Code
}
I want to retrieve some data from database based on some condition, for this I'm using LINQ. But problem is that I don't know how to write LINQ when some condition may be null.
from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
where x.CreatedOn >= model.StartDate && x.CreatedOn <= model.EndDate && x.ClientId == model.ClientId && x.Type == model.Type && x.WorkOrderStatus == model.Status
select new DateWisedReportItemModel
I want if the clientID, type, status have null value then it will take all the values saved in the DB. and if there are some values provided in it, then it will work according to the condition.
I presume you're asking how to wildcard things that are null. You need to make the particular clause true if your model value is null. You could do this by saying things like:
(dbcolumn == modelvalue || modelvalue == null) && ...
Or like
(dbcolumn == modelvalue == null ? dbvalue : modelvalue) && ...
Or like
(dbcolumn == modelvalue ?? dbvalue)
For example:
from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
where
(x.CreatedOn >= model.StartDate ?? x.CreatedOn) &&
(x.CreatedOn <= model.EndDate == null ? x.CreatedOn : model.EndDate) &&
(x.ClientId == model.ClientId || model.ClientId == null) &&
...
I prefer the first as it is the most easy to understand. Also note carefully that it is the only one that will return the row if the row value in the db is null, because to a database null is never equal to null
I want if there is no condition given in ClientId, type and status then only date(this is mandatory) filter will apply, and if there is condition in these only then these(clientId, type and status) conditions will work
It might be most simple, in terms of code readability to do like:
var baseQuery = from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
IEnumerable<...> result;
if(model.ClientId == null && model.Type == null && model.Status == null){
//search on date only
result = baseQuery.Where(x.CreatedOn >= model.StartDate && x.CreatedOn <= model.EndDate);
} else {
//search on no null client/type/status only
result = baseQuery.Where(x =>
(x.ClientId == model.ClientId || model.ClientId == null) &&
(x.Type == model.Type || model.Type == null) &&
(x.WorkOrderStatus == model.Status || model.Status == null);
}
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)
)
Hi any suggestions on building a LINQ statement based on search criteria?
I'll be passing in an instance of a 'SearchCriteria' class with all parameters nullable.
I then want to
if (sc.a != null)
// add to where
if (sc.b != null)
// add to where
The key thing is these are to be ORs not ANDs.
Any tips?
And for bonus points I'd like to use 'contains' on an int? but I can only get equals or not equals.
Try:
.Where(x =>
(x.a != null ? x.a == a : false) &&
(x.b != null ? x.b == b : false));
or
.Where(x =>
(x.a != null && x.a == a) ||
(x.b != null && x.b == b));
Also:
.Where(x => new int[] { 1, 2, 3 }.Contains(x.i));