Need some help on a somewhat complex LINQ query - linq

I have this query that does what I want which is to return true if any of the materials is comparable in the material groups list.
mgroup.MaterialGroups.Select(x => x.Materials
.Any(m => Convert.ToBoolean(m.Comparable)))
.Any(x => x.Equals(true))
What I would like to add to this query is to also include this one.
mgroup.Materials.Any(m => Convert.ToBoolean(m.Comparable));
How can I combine mgroup and it's materialgroups together in the query so I can select both of their Materials? Thanks.
EDIT - After fighting with LINQ for awhile I broke down and just combined as
mgroup.Materials.Any(m => Convert.ToBoolean(m.Comparable) ||
mgroup.MaterialGroups.Select(x => x.Materials
.Any(c => Convert.ToBoolean(c.Comparable)))
.Any(x => x.Equals(true)))
It works as expected but it's horribly long and it's embedded in an Asp.net MVC view to makes things even worse. If anyone can simplify this that would be amazing.
P.S.- If you are wondering why I added the extra .Any(x => x.Equals(true) at the end it's because without it the query returns an IEnumerable of bools instead of bool.

IEnumerable<Material> allMaterials =
mgroup.Materials.Concat(
mgroup.MaterialGroups.SelectMany(group => group.Materials));
bool result = allMaterials.Any(m => Convert.ToBoolean(m.Comparable));

Related

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.

filtering a collection by its children in linq to entities?

I have the following query which filters the batches according to whether the items in the batches have a certain issue no. I would like to know if there is more concise way doing this which would look cleaner.
neptuneBatches =
neptuneBatches.Where(
b => b.Items.Any(
i => i.ItemOrganisations.Any(
s => s.Issues.Any(
x => x.Code == filter.IssueNo))));

Reach Related Entities' Attributes

I get an entity list by following:
var riscregions = db.RiscEntranceDetails.OrderBy(r => r.RiscEntranceID).Include(r => r.RiscEntrance).Include(r => r.RiscRegion);
However, I need to reach more deeply related entities attributes, such as:
<td>#item.RiscEntrance.ID</td>
<td>#item.RiscEntrance.Personnel.Name</td>
<td>#item.RiscEntrance.EntranceDateTime</td>
<td>#item.RiscEntrance.ShiftWork.ShiftGroup.TextID</td>
How can I reach those? Any suggestions including linq, or some other workarounds such as extensions and helpers are greatly appreciated.
You can do this:
var riscregions = db.RiscEntranceDetails
.OrderBy(r => r.RiscEntranceID)
.Include(r => r.RiscEntrance)
.Include(r => r.RiscEntrance.Personnel)
.Include(r => r.RiscEntrance.ShiftWork.ShiftGroup)
You need to use Select in your Include expression only if you need to select children of a collection.
http://msdn.microsoft.com/en-us/data/jj574232.aspx
See eagerly loading multiple levels. You can use .Select() in your .Include() lambda.

LINQ to compare item in one list to any item in another

I wonder, if someone could help me...
Is there a LINQ query that will return a bool, if any item from one IList<> is contained int another IList<>.
These IList<>'s are object and I need to compare one a single property of the object, the "Name" property in this case?
Is there a LINQ query that can do this? If so could someone show me the correct implementation?
Thank you
Well you could project both lists:
if (list1.Select(x => x.Name)
.Intersect(list2.Select(x => x.Name))
.Any())
Is that what you're after?
I think this should do it:
bool matchExists = list1.Any(a1 => list2.Any(a2 => a1.Name == a2.Name));
Another one for your options:
List1.Where(l => List2.Select(s => s.Name).Contains(l.Name)).Any();
I usually use it like below:
List<UserInfo> userUpd = nd.Where(x => !rd.Any(y => y.Identifier.Equals(x.Identifier))).ToList();

How do I merge two LINQ statements into one to perform a list2.Except(list1)?

Currently, I have the following LINQ queries. How can I merge the two queries into one. Basically, write a LINQ query to bring back the results I'd get from
IEnumerable<int> deltaList = people2010.Except(allPeople);
except in a single query.
var people2010 = Contacts.Where(x => x.Contractors
.Any(d => d.ContractorsStatusTrackings
.Any(date => date.StatusDate.Year >= 2010)))
.Select(x => x.ContactID);
var allPeople = Contacts.Where(x => x.Contractors
.Any(m => m.ContactID == x.ContactID))
.Select(x=> x.ContactID);
Thanks!
Why can you not just do Except as you are doing? Don't forget that your people2010 and allPeople variables are just queries - they're not the data. Why not just use them as they are?
If that's not acceptable for some reason, please give us more information - such as whether this is in LINQ to Object, LINQ to SQL etc, and what's wrong with just using Except.
It sounds like you're just looking for a more elegant way to write your query. I believe that this is a more elegant way to write your combined queries:
var deltaList =
from contact in Contacts
let contractors = contact.Contractors
where contractors.Any(ctor => ctor.ContractorStatusTrackings
.Any(date => date.StatusDate.Year >= 2010))
&& !contractors.Any(m => m.ContactID == contact.ContactID)
select contact.ContactID

Resources