How do I simplify a LINQ query with multiple .Select() in order to return an IQueryable(int) - linq

In the LINQ query below, I want to return the ContractorId found in the Contractors table. Not all people in the Contacts table are in the Contractors table. What I really want is a list of ContractorIds for those contractors meeting the criteria. ContractorId is not the same as ContactId.
var contractorsWithCertsFor2010 = dc.Contacts.Where(x => x.Contractors
.Any(d => d.ContractorStatus
.Any(date => date.StatusDate.Year >= 2010)))
.Select(x => x.Contractors
.Select(dr => dr.ContractorId));
IEnumerable<int> differenceQuery = allPeople.Except(contractorsWithCertsFor2010);
allPeople is a IQueryable<Int> but contractorsWithCertsFor2010 is a IQueryable<IEnumerable<Int>>. Something isn't right there. The multiple .Select() is causing the IQueryable<IEnumerable<Int>> so I'm looking for a way to eliminate one of the .Select() and get a return of
IQueryable<Int>
Any Suggestions? Thanks!
Solution:
One solution is posted in a reply below. I created another solution prior to seeing that one. In my solution, I started out in the Contractors table instead of the Contacts table, eliminating one layer and one .Select() statement.

Assuming you only want contractors that have contact record and since the only thing you selecting is the contractor id, you might want to try this:
var contractorsWithCertsFor2010 = dc.Contractors
.Where(c => c.Contacts.Any() && c.ContractorStatus
.Any(cs => cs.StatusDate.Year >= 2010))
.Select(c => c.ContractorId);

First thought: Try SelectMany to flatten your results. So, identical code except for:
//...
.SelectMany(x => x.Contractors
.Select(dr => dr.ContractorId));
IEnumerable<int> differenceQuery = allPeople.Except(contractorsWithCertsFor2010);

Related

How to improve performance of LINQ query to get many fields from a table

Suppose, I have a table called Accounts which has information like
bool isManaged,
double CurrentTotalBalance,
double CurrentManageableBalance,
AccountDetails AccountDetail table,
around 20 fields and 5 different tables
I want to write a query that can select only the field that I need not all of the tables as it reduces my performance.
Currently, I have something like this,
This is just a sample code, but not the working code.
var accounts = await _context.Accounts
.Include(x => x.Plan)
.Include(x => x.AccountDetails)
.Where(x => x.Plan.Id == 123)
.ToListAsync();
Then I am going, over the accounts list and getting the required results.
It works great for smaller plans but when I have larger plans it loads so many accounts.
So, is there a way to get data from it,
I was thinking something like this,
This is just a sample code, but not the working code.
var accounts = await _context.Accounts
.Include(x => x.Plan)
.Include(x => x.AccountDetails)
.Where(x => x.Plan.Id == 123)
.Select(x => new
{
PlanAssets = x.Sum(x => x.CurrentTotalBalance),
PlanParticipants = x.Accounts.Count,
OutsideAssets = 123,
ManagedParticipants = x.Where(x => x.IsManaged == 1).Count()
})
.ToListAsync();
But the problem with this is I am getting a list of each account. I want to sum up all the CurrentTotalBalance in the accounts table.
Is there a way to get the list of those fields which are required only from the accounts table and query them? I am having a performance issue. Any recommendation to improve the performance would be appreciated.

Select two lists as one list in ASP.NET Core linq

I am trying to create a query with ASP.NET Core EF Core and Linq that would give me a List of users based on two different lists, something like this:
return await _context.Users
.Include(u => u.PropertyOwners)
.ThenInclude(po => po.Property)
.ThenInclude(p => p.PropertyTenantLeases)
.Include(u => u.PropertyOwners)
.ThenInclude(po => po.Owner)
.Where(u => u.Id == userID)
.Select(u => new List<User>()
{
u.PropertyTenantLeases.Select(ptl => ptl.Tenant).ToList()
u.PropertyOwners.Select(po => po.Owner).ToList()
}).FirstOrDefaultAsync();
The tables that are used in this query are connected in the following way:
Everything is fine with this query except for the Select, with the Select I am trying to achieve that it returns a list of all the tenants in the PropertyTenantLeases table which is a junction table togheter with all the Owners form the PropertyOwners junction table (both Tenant and Owner are IdentityUser classes. When I right this query like this I get the following error:
The best overloeaded Add method 'List<User>.Add(User)' for the collection initializer has some invalid arguments
and also
Argument 1: cannot convert from 'System.Collections.Generic.List<RosyMasterDBManagement.Models.User>' to 'RosyMasterDBManagement.Models.User'
Joining two list is called a union in Linq -- I believe that is what you want:
note: I still can't test this since you gave a picture of the data model instead of the code that would allow me to be certain of how to implement. expect the fields to be named incorrectly etc.
var ownerlist = _context.Users
.Include(u => u.PropertyOwners)
.ThenInclude(po => po.Owner)
.ToList();
var tenantlist = _context.Users
.Include(u => u.PropertyOwners)
.ThenInclude(po => po.Property)
.ThenInclude(p => p.PropertyTenantLeases)
.ThenInclude(po => po.Tenant)
.ToList();
return ownerlist.Union(tenantlist);
I don't believe you need await() since ToList() forces it to not be lazy. But I could be wrong about that.

JoinQueryOver in QueryOver to select notin list

I have a list of record that I picked up through the code:
var list= NhSession.QueryOver<Data.Models.MembModel>()
.Where(w => w.Comp.Id == idcomp)
.JoinQueryOver(jq => jq.Ver)
.Select(s => s.Ver)
.List<Dados.Models.VerModel>();
With this code I get a list of VerModel that I have relation in a MembModel. The problem is that I what get the list of VerModel that don't be in relation in a MembModal, I think to describe this, I want to select one list that is "notin" a first list. How can I do this?
Tks
What we need, as you said, is a NOT IN (subquery) statement. And NHibernate does have a clear way how to achieve that. First the subquery, which will return MembModel collection (filtered or not - as needed), represented by the VerModel.ID
var subquery = QueryOver.Of<Data.Models.MembModel>()
// we can still filter this sub-select ... or not
// .Where(w => w.Comp.Id == idcomp)
// what we need to be returned is the reference id, the VerModel.ID
.Select(m => m.Ver.ID);
And now we will query the VerModel itself, with the NOT IN (subquery) clause:
var list = session.QueryOver<Dados.Models.VerModel>()
.WithSubquery
.WhereProperty(v => v.ID) // the ID to match the prev selected one
.NotIn(subquery) // should NOT be IN
.List<Dados.Models.VerModel>();
Check:
16.8. Subqueries

Finding n-Most Popular Using Linq

How should I structure a Linq query to return a List or Ienumerable of the most popular Tags in my db (I am using EF4.1 by the way).
Currently I have:
var tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5)
.Select();
I think I am part of the way there, but I am unsure of how to structure the Select statement...
Your Select call could look like this:
.Select(gp => gp.Key)
That will give you an IEnumerable<string> of your most popular tags (assuming that Name is a string).
Assuming you want the name and the count, just:
.Select(g => new { Name = g.Key, Count = g.Count() });
EDIT: If you want the complete tags as well, you could use:
.Select(g => new { Tags = g, Count = g.Count() })
which would give you a sequence of groups of tags, all with the same name within a group. Or you might only want the first tag within each group, e.g.
.Select(g => g.First())
It's not clear what a Tag consists of, or what exactly you want in the results.
You've written a perfectly workable query and do not need to call .Select
IQueryable<IGrouping<string, Tag>> tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5);
List<IGrouping<string, Tag>> results = tagListing.ToList();
You probably want to select the names like this:
.Select(gp => gp.Key);

How to return distinct rows from and Entity with related Entities

I have an Entity that has an association to other Entities (related entities). I'm trying to return distinct rows from the primary entity which needs to include the data from the related entity so I can use one the related entity's properties downstream.
Below is the statement I'm using but it is not returning any rows. What's the best way to do this?
Below is my code.
return context.UserDisplays.Include("CurrentJob").Where(d => d.UserName == userName).GroupBy(d => d.CurrentJob.JobNo).Select(g => g.FirstOrDefault()).ToList();
Any help would be greatly appreciated!
Edit - For ComplexProperty
I believe once you do a GroupBy all Include methods are ignored. So you will need to iterate the list and call the LoadProperty method on each item. It should look something like this
var list = context.UserDisplays
.Where(d => d.UserName == userName)
.GroupBy(d => d.CurrentJob.JobNo)
.Select(g => g.FirstOrDefault()).ToList();
foreach(var item in list)
{
context.LoadProperty(item, "CurrentJob");
}
return list;
Resource Link
Check out the Distinct (Set Operators) section in this article
http://msdn.microsoft.com/en-us/vcsharp/aa336746
Are you asking for the Distinct UserDisplays? or the Distinct User or the Disticnt Jobs?
I would try say something like
var object = (from userDisplay in context.UserDisplays.Include("CurrentJob")
.Where userDisplay.UserName == userName
Select userDisplay).Distinct();
(sorry, im going off of my VB style but it should be about the same...)

Resources