Linq: additional parameter - c#

I have the following line:
orderBaseData.Single(o => o.Id == order.Id).OrderMessages.Count;
I want to filter this a bit more. Each OrderMessage has a variable called hideFromUser, and I want to get the count of the OrderMessages where this is set to FALSE only.
Thanks in advance,
Bob

Use Where on OrderMessages
orderBaseData
.Single(o => o.Id == order.Id)
.OrderMessages
.Where(x => !x.hideFromUser)
.Count();

In order to retrieve the data efficiently in a single query, instead of relying on LazyLoading the OrderMessages afterwards, you could use the following:
orderBaseData
.Where(o => o.Id == order.Id)
.Select(o => o.OrderMessages.Where(x => !x.hideFromUser).Count())
.Single();
This approach is mostly interesting when orderBaseData is some IQueryable targeting a database. If all the data are already in memory, then it is not really better or worse than the other approaches.

Related

How can I order in Linq Select Distinct if ordered by an Included entity?

I know that in Linq I have to do the OrderBy after doing a Select - Distinct, but I'm trying to order by an Included entity property that get lost after the Select.
For example:
var accounts = _context.AccountUser
.Include(o => o.Account)
.Where(o => o.UserId == userId || o.Account.OwnerId == userId)
.OrderByDescending(o => o.LastAccessed)
.Select(o => o.Account)
.Distinct();
As I'm doing the Where by an or of two different parameters, there is a good chance to obtain duplicated results. That's why I'm using the Distinct.
The problem here is that after I do the Select, I don't have the LastAccessed property anymore because it doesn't belong to the selected entity.
I thing the structure of the AccountUser and Account can be inferred from the query itself.
If you have the bi-directional navigation properties set up:
var accountsQuery = _context.AccountUser
.Where(o => o.UserId == userId || o.Account.OwnerId == userId)
.Select(o => o.Account)
.Distinct()
.OrderByDescending(a => a.AccountUser.LastAccessed);
When Selecting the Account you do not need .Include() Keep in mind that any related entities that you access off the Account will be lazy-loaded. I recommend using a .Select() to extract either a flattened view model or a view model hierarchy so that the SQL loads all needed fields rather than either eager-loading everything or tripping lazy-load calls.
Since LINQ doesn't implement DistinctBy and LINQ to SQL doesn't implement Distinct that takes an IEqualityComparer, you must substiture GroupBy+Select instead:
var accounts = _context.AccountUser
.Include(o => o.Account)
.Where(o => o.UserId == userId || o.Account.OwnerId == userId)
.GroupBy(o => o.Account).Select(og => og.First())
.OrderByDescending(o => o.LastAccessed)
.Select(o => o.Account);

Merge results of 2 LINQ To SQL queries and keep their ordering

I need to append the results of one LINQ To SQL query to another on the database server side without reordering rows.
I need all errored orders first, then the pending orders.
var error = database.Orders.
Where(o => o.Status == XOrderStatus.Error).
OrderByDescending(o => o.Id);
var pending = database.Orders.
Where(o => o.Status == XOrderStatus.PendingReview).
OrderByDescending(o => o.Id);
var r = error.OrderedUnion(pending);
How I can implement the OrderedUnion() method? Concat, Union and Distinct methods completely eliminate OrderByDescending call (by design).
I know it is possible to do with two ToArray() calls, but I am interested having this done at the database level.
You can concatente them together and then order by a column that seperates the order groups. so for instance in an SQL Query you would do this:
ORDER BY XOrderStatus, Id
and that would order by ID but with the two OrderStatuses grouped.
I don't know linq to sql (sorry!) but a quick Google mentioned this may work:
.Orderby(o => o.XOrderStatus).ThenBy(o => o.Id)
Original Source:
Multiple "order by" in LINQ
I found much better solution:
var all = database.Orders.
Where(o =>
o.Status == XOrderStatus.Error ||
o.Status == XOrderStatus.PendingReview).
OrderBy(o => o.Status == XOrderStatus.Error ? 0 : 1).
ThenByDescending(o => o.Id).
ToArray();

Linq query to sort collection

i have custom a collection LoanOptionsProgramVersionList which has bolean property Configured,string Description and Code.While insert and delete from the collection i want sort the collection in the below order. So one record inserted to database configured become yes. When deleted Configured become "No". So it Notify property.
sort by configured
then by description
then by code
i have tried the below code After insert.
IOrderedEnumerable<ProgramVersionRecord> orderedList =
LoanOptionsProgramVersionList
.OrderByDescending(p => p.ProgramVersionConfigured == true);
Also below code for deletion
IOrderedEnumerable<ProgramVersionRecord> orderedList =
LoanOptionsProgramVersionList.OrderBy(p => p.Description);
Any help will be appreciated.
Use ThenBy
IOrderedEnumerable<ProgramVersionRecord> orderedList = LoanOptionsProgramVersionList
.OrderByDescending(p => p.ProgramVersionConfigured) // configured has priority
.ThenBy(p => p.Description)
.ThenBy(p => p.Code);
When ordering by ProgramVersionConfigured property use this property instead of result of comparison with boolean. Also use ThenBy to add another sorting:
LoanOptionsProgramVersionList.OrderByDescending(p => p.ProgramVersionConfigured)
.ThenBy(p => p.Description)
.ThenBy(p => p.Code)

Remove duplicates of a List, selecting by a property value in C#?

I have a list of objects that I need some duplicates removed from. We consider them duplicates if they have the same Id and prefer the one whose booleanValue is false. Here's what I have so far:
objects.GroupBy(x => x.Id).Select(x => x.Where(y => !y.booleanValue));
I've determined that GroupBy is doing no such grouping, so I don't see if any of the other functions are working. Any ideas on this? Thanks in advance.
You can do this:
var results =
from x in objects
group x by x.Id into g
select g.OrderBy(y => y.booleanValue).First();
For every Id it finds in objects, it will select the first element where booleanValue == false, or the the first one (if none of them have booleanValue == false).
If you prefer fluent syntax:
var results = objects.GroupBy(x => x.Id)
.Select(g => g.OrderBy(y => y.booleanValue).First());
Something like this should work:
var result =
objects.GroupBy(x => x.Id).Select(g =>
g.FirstOrDefault(y => !y.booleanValue) ?? g.First())
This assumes that your objects are of a reference type.
Another possibility might be to use Distinct() with a custom IEqualityComparer<>.
This partially answers the question above, but I justed need a really basic solution:
objects.GroupBy(x => x.Id)
.Select(x => x.First())
.ToArray();
The key to getting the original object from the GroupBy() is the Select() getting the First() and the ToArray() gets you an array of your objects, not a Linq object.

LINQ Queries Comparison

I have 2 LINQ Queries here, i just want to know which of these query is proper and fast to use.
Sample I
var GetUSer = (from UserItem in dbs.users
where UserItem.UserID == UserID
select new User(UserItem))
.OrderBy(item => item.FirstName)
.Skip(0)
.Take(10)
.ToList();
Sample II
var GetUSer = (from UserITem in dbs.user
.Where(item => item.UserID == UserID)
.OrderBy(item => item.FirstName)
.Skip(0)
.Take(10)
.AsEnumerable()
select new User(UserItem)).ToList();
Although they are both working well, i just want to know which is the best.
The Second one is better, the first 1 does a select then does filtering, meaning it has to get the data from the database first to turn it into a User object, then it filters.
The second one will do the query on the DB side, then turn it into a User object
The first one can be fixed by moving the select till just before the ToList()
Between those two, I would prefer the first (for readability, you'd need to switch some things around if you want the whole query to execute in the database). If they both work, it's up to you though.
Personally, I don't like mixing query syntax with lambda syntax if I don't have to, and I prefer lambda. I would write it something like:
var GetUsers = db.user
.Where(u => u.UserID == UserID)
.OrderBy(u => u.FirstName)
.Take(10)
.Select(u => new User(u))
.ToList();
This uses a single syntax, queries as much as possible in the database, and leaves out any superfluous calls.

Categories

Resources