OrderByDescending with multiple fields - c#

I want to be able to sort by d.DateUpdated but only when it's not DateTime.MinValue. If it's DateTime.MinValue then I would need it to be able to sort by d.DateCreated. It there a way to do this with in the following line of code?
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated)
.ToListAsync();

You might as well use ThenBy method
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated)
.ThenByDescending(d => d.DateCreated)
.ToListAsync();

Something like that?
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated == null ? d.DateCreated : d.DateUpdated)
.ToListAsync();

Related

linq to entities skip after concat

I want to display results that don't have a secondary ID displayed first and then display items that do have a secondary ID. But then I need to Skip and Take.
IQueryable<thing> result;
IQueryable<thing> result2;
result2 = result
.Where(t => !(t.second_id == null || t.second_id.Trim() == string.Empty))
.OrderBy(t => t.second_id);
result = result
.Where(t => (t.second_id== null || t.second_id.Trim() == string.Empty))
.OrderBy(t => t.first_id);
result = result.Concat(result2);
return result
.Select(t => t.primary_key)
.Skip(pageSize * pageNumber)
.Take(pageSize)
.ToList();
The problem is that after Concat the IQueryable is no longer technically ordered so Skip and Take throw an error. Like this:
PagedList error: The method 'OrderBy' must be called before the method 'Skip'
You can do it in one query with the conditional operator:
return result.OrderBy(t => (t.second_id != null && t.second_id.Trim() != String.Empty))
.ThenBy(t => (t.second_id != null && t.second_id.Trim() != String.Empty) ? t.second_id : t.first_id)
.Select(t => t.primary_key)
.Skip(pageSize * pageNumber)
.Take(pageSize)
.ToList();
It would need some adjustment if you need to order duplicate second_id in some way, but your original code doesn't.
PS I folded in the negation operator since I think it reads more clearly.
You can do the job with a single query
result = result
.OrderByDescending(t => (t.second_id== null || t.second_id.Trim() ==
string.Empty))
.ThenBy(t => t.second_id)
.ThenBy(t => t.first_id)
.Select(t => t.primary_key)
.Skip(pageSize * pageNumber)
.Take(pageSize)
.ToList();

C# Linq multi-word search

I have the following, where searchby is a string
var products = db.Products
.Where(p => p.Category.Name == category
&& p.Active == true
&& (searchby == null || (searchby != null && p.Keywords.Contains(searchby))))
.Include(p => p.Category)
.OrderBy(p => p.Description)
.ThenBy(p => p.Name);
and would like to change it to allow searchby to contain multiple words which would filter the results to records where Keywords contains all of the words in searchby.
Thanks in advance
You can use another collection and either Enumerable.All(not sure if supported by your LINQ provider) or !Enumerable.Any:
List<string> searchby = ... (empty if there is no filter)
var products = db.Products
.Where(p => p.Category.Name == category
&& p.Active == true
&& !searchby.Any(s => !p.Keywords.Contains(s)))
.Include(p => p.Category)
.OrderBy(p => p.Description)
.ThenBy(p => p.Name);
If supported this is more readable:
&& searchby.All(s => p.Keywords.Contains(s)))
This answer assumes, that searchby is either null or an Array.
Since contains only checks for 1 item, you need to find a way to check for all items within searchby. The Enumerable.All-Method comes to mind. Here is the relevant part:
searchby.All(searchItem => p.Keywords.Contains(searchItem))
Source

LinQ to get the latest group of records satisfying a condition

I have below stated 2 tables:
now I want to get the set of Child Table objects for whichever their parent table entries are latest(wr.r.t lastmodified). It should be something like....
List<Child_Table> List = ChildsList.Where(x=>x.name =="pqr" && status == "done")
.Select(x=>x.Parent.lastmodified == recent record).....ToList();
You can use GroupBy on the date, then OrderByDescending on the Key then take the First followed by SelectMany to flatten the results.
var result = ChildsList.Where(x => x.name == "pqr" && x.status == "done")
.GroupBy(x => x.Parent.lastmodified)
.OrderByDescending(g => g.Key)
.First()
.SelectMany(g => g)
.ToList();
You could use a join to accomplish it:
var results = children
.Join(parents.OrderByDescending(p => p.lastmodified).Take(1),
c => c.parent_id,
p => p.id,
(c, p) => c)
.Where(x => x.name == "pqr" && x.status == "done")
.ToList();

Ordering and subordering a list using a lambda

I need to order a list by status == "Rejected" and date ascending and then by status == "Accepted" and date descending.
I am trying the following but I'm not sure how to go about this:
items
.OrderBy(x => x.status == "Rejected")
.ThenBy(x => x.DateSubmitted)
.ThenBy(x => x.status == "Accepted")
.ThenByDescending(x => x.DateSubmitted)
You're describing the task a bit awkward, which (I think) leads you to a slightly wrong implementation.
I say:
items
.Where(x => x.status == "Rejected")
.OrderBy(x => x.DateSubmitted)
.Concat(items.
.Where(x => x.status == "Accepted")
.OrderByDescending(x => x.DateSubmitted));
The main difference is that now, status other than "Rejected" or "Accepted" are not shown.
However, I think it is what you intended. If you want the full set, consider using
items
.Where(x => x.status == "Rejected")
.OrderBy(x => x.DateSubmitted)
.Concat(items.
.Where(x => x.status != "Rejected")
.OrderByDescending(x => x.DateSubmitted));
PS. This is also assuming Linq-To-Objects. I'm not very well-versed with Linq-to-EF or Linq-to-SQL

Linq to SQL / C#: How to Order By using property in cross reference table with lambda expressions

I am trying to order a list of products based on the zindex property of the cross reference table with the category table (in this case called 'Chassis'), but I get the following error:
Cannot order by type 'System.Collections.Generic.IEnumerable`1[System.Int32]'.
The following is the method I am using:
public IQueryable<E_Product> Product_GetList_ByChassisId(int chassisId)
{
return dc.E_Products
.Where(x => x.Deleted == false)
.Where(x => x.Published == true)
.Where(x => x.E_Product_Chassis
.Any(c => c.ChassisId == chassisId && c.Deleted == false))
.OrderBy(x => x.E_Product_Chassis.Select(c => c.Zindex));
}
I understand the .Select method returns an IEnumerable, but being a many-to-many relationship, x.E_Product_Chassis does not allow simple selection of its properties (e.g. x.E_Product_Chassis.Zindex).
Any help would be very appreciated...
FirstOrDefault(), Min(), Max() -- use one of these functions to select the appropriate z-index out of the set.
public IQueryable<E_Product> Product_GetList_ByChassisId(int chassisId)
{
return dc.E_Products
.Where(x => x.Deleted == false)
.Where(x => x.Published == true)
.Where(x => x.E_Product_Chassis
.Any(c => c.ChassisId == chassisId && c.Deleted == false))
.OrderBy(x => x.E_Product_Chassis.Min(c => c.Zindex));
}

Categories

Resources