LINQ Conditional OrderBy - c#

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);
....

Related

c# linq question about multiple where clauses

I am trying to query a database with multiple where clauses.
IQueryable<string> statusQuery = from m in _context.Flight
where m.Aircraft_Type == aircraftType
&& m.Identification_Registration == registration
&& m.Destination_Airport_City == to1
&& m.DepartureDate.ToString("yyyy-MM-dd") == date1
&& m.Origin_Airport_City == from1
orderby m.Status_Text
select m.Status_Text;
This code is working, but only if I am able to supply a value to each variable.
How can I use this with a check if e.g registration == null => do not check use
&& m.Identification_Registration == registration
if(...) doesn't work here.
You can emulate this behavior using logical operators:
IQueryable<string> statusQuery =
from m in _context.Flight
where m.Aircraft_Type == aircraftType
&& (registration == null || m.Identification_Registration == registration)
&& m.Destination_Airport_City == to1
&& m.DepartureDate.ToString("yyyy-MM-dd") == date1
&& m.Origin_Airport_City == from1
orderby m.Status_Text
select m.Status_Text;

Include in where statment only if not null

I have the following :
how can i include a filter in my where statement only if it's not null?
i tried the following but i always get 0 records
public async Task<IList<UserRefDto>> GetUserRef(Dictionary<string, string> filter) {
var iod = 549; // a test user who has 2548 records in db
var favorites = filter.ContainsKey("fav") ? filter["fav"].ConvertToGuid(",") : null;
var histories = filter.ContainsKey("his") ? filter["his"].ConvertToGuid(",") : null;
var orders = filter.ContainsKey("ord") ? filter["ord"].ConvertToGuid(",") : null;
var result = await context.UserRefernces
.Where(x =>
x.User_iod = iod
&& (favorites != null && favorites.Contains((Guid)x.FavId))
&& (histories != null && histories.Contains((Guid)x.HistoryId))
&& (orders != null && orders.Contains((Guid)x.OrderId))
)
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
return result;
}
EDIT
Note: If all keys have values then i got records back, only if one or more is null i got nothing back from db
You can build your query with several .Where() statements, which will be added via an AND condition. But add the additional .Where() statements only when the values are present.
var query = context.UserRefernces
.Where(x => x.User_iod == iod);
if (favorites != null) {
query = query.Where(x => favorites.Contains((Guid)x.FavId));
}
// same for "histories" and "orders"
var result = await query
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
Replace favorites != null && with favorites == null || in your query as follows:
var result = await context.UserRefernces
.Where(x => x.User_iod = iod
&& (favorites == null || favorites.Contains((Guid)x.FavId))
&& (histories == null || histories.Contains((Guid)x.HistoryId))
&& (orders == null || orders.Contains((Guid)x.OrderId)))
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
return result;
Now the query will work as expected.

limiting by an additional LINQ parameter

I have the following in an MVC application:
var selectedArticles =
vm.Articles.Except(
vm.Articles.Where(x => x.Quantity == 0)).ToList();
I need to add another parameter. I DONT want to show the articles where the option HideUntilDate != NULL && HideUntilDate > todays date
Any tips?
Except not needed
var selectedArticles = vm.Articles
.Where(a => a.Quantity == 0 && !(a.HideUntilDate != null && a.HideUntilDate.Value > DateTime.Today));
Just add the requirement logic to your where clause's lambda expression
var selectedArticles =
vm.Articles.Except(
vm.Articles.Where(
x => x.Quantity == 0 ||
x.HideUntilDate == null ||
x.HideUntilDate < DateTime.Now.Date()
)
).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));

Conditional WHERE in LINQ

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));

Categories

Resources