Select All from Collection Where ID in List - c#

I'm just learning to use lambda expressions and was turned on to Dapper a couple days ago. I'm working on an app that populates a listView with usernames to be selected for some account maintenance. I'm having trouble with one part of sorting:
I'm getting a collection of objects using a Dapper query and assigning it to the variable Global.allUsers.
I have a list of IDs (List<int> migrated) that have already been used, and so don't need to appear in the listView
I'm getting a list of all my users using the following:
var uniqUsers = Global.allUsers.OrderBy(n => n.lastNames).GroupBy(q => q.salesIDs);
To populate the listView with only the users who haven't been migrated, I need to select only those users without q.salesIDs in migrated. I just can't quite figure out if/how I can do this without using some kind of foreach. Seems like there should be a way to select it.
Granted, I'm looping through uniqUsers anyway, and populating the listView with values out of each object's properties. I can add a statement to check if the current ID is in migrated, but my gut is just telling me that I can do it with the select statement and save myself a step.
I'm thinking something like this:
var uniqUsers = Global.allUsers.Where(i => i.salesIDs not in migrated).OrderBy(n => n.lastNames).GroupBy(q => q.salesIDs);
but i => i.salesIDs not in migrated isn't cutting it.

This does what you need:
var uniqUsers = allUsers.Where(x => migrated.Contains(x.salesIDs))
.OrderBy(y => y.lastNames)
.GroupBy(z => z.salesIDs).SelectMany(v => v).ToList();
Gets all users where the salesID is in migrated, then orders by lastNames and then groups by the salesID. The SelectMany() will project the elements to a sequence, the ToList() will enumerate the results.

Related

How is it possible that selecting first after GroupBy on a DataTable does not return one value for every group?

I am trying to get one row per id from a DataTable, and I do not care which row I take. The same id can exist on several rows in the table.
Here's the expression that's giving me trouble:
dt.AsEnumerable().GroupBy(i => i.Field<int>("id")).Select(i => i.First())
Running just this section dt.AsEnumerable().GroupBy(i => i.Field<int>("id") correctly gives me a result of 22 groupings for my DataTable. (I have 22 ids with data in this table)
However, when adding on the .Select(i => i.First()), I am only seeing 10 data rows.
To me this doesn't seem to make any sense. If the GroupBy function managed to find 22 distinct id values, I would expect this logic to grab one of each.
My only other thought is that maybe it's just a weird side effect of viewing this data through a watch in Visual Studio rather than assigning to a variable.
If you think it's just weird side effects of viewing the data in a watch, which can happen with LINQ statements, then split it out into
var groups = dt.AsEnumerable().GroupBy(i => i.Field<int>("id")).ToList();
var firstOfGroups = groups.Select(i => i.First()).ToList();
and then look at groups and firstOfGroups in the debugger. Temporarily evaluating items with .ToList() can help a lot with viewing things in the debugger.
I think it is possible, can double check the count of each group items
.Select(g=>new { k = g.Key, c = g.Count() })

Linq filters required on Project Context object

I am trying to get a filtered list from MS Project and filter on the name by using something akin to contains so that we can return a reduced set of results to process.
projContext.Load(projContext.Projects, qp => qp.Include(qr => qr.Id, qr => qr.Name));
I seem to have exhausted all the options that I know about and trying to use contains isn't working for me.
Intellisense allows this . . . (but doesn't like it at run time)
projContext.Load(projContext.Projects, qp => qp.Include(qr => qr.Id, qr => qr.Name.Contains("myfilter")));
I dont know if i am understanding what is your difficulty but, to obtain the list of projects filtered by " name contains the 'myfilter'. Try this
using (var context = new projContext())
{
var projects = context.Projects.Where(p => p.Name.Contains("myfilter")).ToList();
}
https://learn.microsoft.com/en-us/ef/core/querying/related-data
.Include() is an EF Query extension that includes the navigation property you requesting, since Id and Name ( can't know for certain since you didn't provided your model class ) most certainly are values stored in the database you don't have to Include them on your query. If you are looking to filter by contains to minimize the result of your query simply add a to your query your filters like so :
projContext.Projects.Where(project => project .Name.Contains("myfilter")));

How to speed up a linq statement that checks two lists for missing records

What I am trying to achieve.
I am working on a reconcile process and need to ensure my database table has the correct entries. I need to find records in a table that are not in a master list. When I have found these entries I need to group them and find the most recent in each group. If the operation fields of the most recent entries are defined as “Added”, I will need to add additional records with their operation fields marked as “Deleted”, as they are not defined in the master list.
The code I have written selects records in the database that are not in the master list. It then groups these and orders them and finally select the first item in each group which will now be the newest in each group. I then return only the items that have an operation defined as “Added”. I have run this code against my unit tests and with “real” data. Although it works, it is very slow taking maybe forty seconds when run against a database of 16 thousand records (when run from within visual studio). Can anyone advise on if it is possible to modify my code to improve the speed?
Shown below is the code that finds the mismatched records
var linksInDb = _ctx.LinkRecords.ToList();
return (from dbl in linksInDb select dbl)
.Except(
from dbl in linksInDb
from l in links
where dbl.EP1Id == l.Endpoints[0].EntityKey.EntityId && dbl.EP2Id == l.Endpoints[1].EntityKey.EntityId
select dbl)
.GroupBy(x => new {x.EP1Id, x.EP2Id},
(key, g) => g.OrderByDescending(x => x.LastModifiedDate_UTC).First())
.Where(x => x.Operation == "Added")
.ToList();
NB. The master list called "links" is a generic list of type Link which is the same type returned by _ctx.LinkRecords.ToList();

EntityFramework - How to populate child members?

I have been given a model to work with but cannot figure out the LINQ query to get what I need into my object.
Given an initial date, I need to retrieve all of the items posted for sale since then, member details, and the filenames of the photos of those items.
Also need to be able to pass in a MemberID and find which items they have for sale (and filenames)
Can someone please point me to what the query for this would be?
I've been following a few EF tutorials but am having lots of trouble figuring this one out...
When I try this, I get a null reference exception when talking to the photoURL.
var items = db.BuySellLists.Include(b => b.Member)
.Include(b => b.BuySellPhoto)
.Where(b => b.PostedDate >= fromDate && b.IsBuyable == true)
.OrderBy(b => b.PostedDate)
.ToList();
I've currently got it working by looking up all items for sale, then from there looping over each BuySellListId to get that items photos to get the URL, but this causes quite a few individual queries to the database and is giving performance issues.
Photo is not implicitly included in your query. That is why you get a NullReferenceException. You need to include it explicitly as follows:
Include(b => b.BuySellPhoto.Photo)
Check MSDN documentation on Include extension for more details.

Search and select multiples with where linq/lambda expressions

I currently have the following code:
var FirstNameList = db.Clients.Include(x => x.FirstNames).Include(x => x.Addresses).SelectMany(a => a.FirstNames).Where(x => x.Name.ToLower().Trim() == "Max".ToLower().Trim()).ToList();
I have a navigation property of FirstNames and Addresses which I which to include in the result.
I use the SelectMany Statement because it, for me, is the only one which works. Kind of. It returns all the FirstNames where the Name equals Max.
What I would like it to do is return all the Clients who have the property Name equals Max from the table FirstNames.
the other way I thought about doing this was to take all the ID's returned from FirstNameList and then returning the Clients by querying the data against the FirstNameList but I would be then querying the database twice, which seems inefficient.
My question is is it possible, and how would I go about querying the database to return my Clients, if it was?
Kind regards
The following query should give you what you're looking for. You can look within each client's FirstNames and see if any of them are named "max". (In this case, since "max" is a constant you're typing in, I removed the ToLower().Trim() from it)
var clientsNamedMax = db.Clients.Include(x => x.FirstNames).Include(x => x.Addresses).Where(x => x.FirstNames.Any(y => y.Name.ToLower().Trim() == "max")).ToList();

Categories