linq - find item in list within multiple lists - c#

I have a highly nested class, and trying to find a single item buried deep within. The following gives me an error "Can't convert type match to bool', although I don't see why it thinks I'm trying to return a boolean.
var match = community.TeamLeagues
.Where(x => x.Seasons
.Where(y => y.Divisions
.Where(z => z.Matches
.Where(a => a.Id == "1234").FirstOrDefault())));

Where by itself returns a (deferred) enumerable of items and cannot as such be used as a condition by the outer Where. What you probably want to do is to use Contains(), Any() or All() inside the outer Wheres that will return the result you're looking for.
Something like this might be what you're after:
var match = community.TeamLeagues.Where(t =>
t.Seasons.Any(
s => s.Divisions.Any(
d => d.Matches.Any(
m => m.Id == "1234")
)));

The Where method needs to evaluate an expression that returns a bool. Your nested Wheres are not doing that - the only Where that is, is the last one a => a.Id == "1234", all the other expressions are returning an IEnumerable.

z.Matches.Where(a => a.Id == "1234").FirstOrDefault() returns a object of type Match(your collection item type of the IEnumerable Matches) (or null), no boolean value. I guess you need to check if there are entires in matches that have a Id 1234. Use Any to evaluate a condition:
var match = community.TeamLeagues.Where(x =>
x.Seasons.Any(y =>
y.Divisions.Any(z =>
z.Matches.Any(a => a.Id == "1234")
)));
[items.Where(x => x.Id == 4).Any() is the same as items.Any(x => x.Id == 4)]
This returns you all TeamLeagues which contain a Season which contain a Division which contain a Match which has a element with the id 1234.

To make it simple you can also use the Matches table directly and using a ViewModel you can represent your view.
like:
var MyViewModel = (from l in Mathes
where l.Id == "1234"
select new MyViewModel
{
Id = l.Id,
MatchName = l.Name,
}).ToList();

Couldn't get it working with linq, but works with query syntax.
var leagueMatch = (from teamLeague in community.TeamLeagues
from season in teamLeague.Seasons
from division in season.Divisions
from match in division.Matches.Where(x => x.Id == "1234")
select match).FirstOrDefault();

Related

how to use linq to return a value from 4 tables

I am reasonably new to Linq and it seems quite easy to iuse but I am having an issue when trying to extract a value from a table that is linked/constrained by 3 other tables.
I have this in my SQL DB:
I am using Asp.Net 4 and Entity Framework 6.
I have as a parameter the 'DatabaseName'.
I ultimately want to get the SubscriptionRef that is assigned to this name.
I could do this step-by-step (ie using multiple linqs) but I thought it would look 'clean' using just 1 linq statment.
I have got as far as this:
var names = o.RegisteredNames.Where(d => d.DatabaseName == DBName).Where(d => d.ClientNames.Where(f => f.ClientId == f.Client.ClientId).FirstOrDefault();
But I get the error:
Cannot implicitly convert type 'Services.ClientName' to 'bool'
You have a Problem here:
d => d.ClientNames.Where(f => f.ClientId == f.Client.ClientId)
f => ... returns a single ClientName or null, which causes your error, because there should be a boolean.
If you want this first value or null, you should replace
.Where(d => d.ClientNames ...
//with
.Select(d => d.ClientNames ...
Try this:
o.RegisteredNames.First(d => d.DatabaseName == DBName).ClientNames.Select(x=>x.Client.Subscription.SubscriptionRef)
It should give you list go SubscriptionRef.
You can try with one LINQ query like...
var names = o.RegisteredNames.Where(d => d.DatabaseName == DBName ).FirstOrDefault();
You might wanna try sql style:
var client = from c in db.Clients
join cn in db.ClientNames on c.ClientId equals cn.ClientId
join rn in db.RegisteredNames on cn.RegisteredNamesId equals rn.RegisteredNameId
where rn.DatabaseName == "YourDBName"
select c;
But it also depends on how your objects were built.
Try using join:
var names = (
from names in o.RegisteredNames.Where(d => d.DatabaseName == DBName)
join cnames in o.ClientNames on names.RegisteredNamesId equals cnames.RegisteredNamesId
select cnames.ClientId
).FirstOrDefault();
Add as many joins as you want.
Try this
It works in List,
var option1= o.RegisteredNames
.Where(g => g.DbName == "YourDbName")
.Where(h => h.ClientNames.Any(f => f == 5))
.FirstOrDefault();
var option2= o.RegisteredNames
.FirstOrDefault(h => h.DbName == "Name" && h.ClientNames.Any(j => j == 1));

Linq Lambda Where clause with in a where clause

I am trying to build a lambda expression with serval where clauses with in each other.
Items, webProperties and profiles are all lists. I am trying to find the one that contains a profile which is 3 level lists down. Actually all I am really trying to do is validate that it does exist.
var x = AccountSummeriesResponse.items.Where(wp => wp.webProperties.Where(p => p.profiles.Where(a => a.id == profile ))).FirstOrDefault();
I am getting the following error.
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable'
to 'bool'
The probelm is Enumerable.Where returns IEnumarable<T> but the predicate of Where expects a boolen. You can use Any instead:-
var x = AccountSummeriesResponse.items
.Where(wp => wp.webProperties.Any(p => p.profiles.Any(a => a.id == profile )))
.FirstOrDefault();
Also, you can replace the Where with FirstOrDefault like this:-
var x = AccountSummeriesResponse.items
.FirstOrDefault(wp => wp.webProperties.Any(p => p.profiles
.Any(a => a.id == profile )));
That's because delegate(Predicate) inside the where clause needs to return bool and you are returning IEnumerable(Where(p => p.profiles.Where(a => a.id == profile ))) so reporting a compilation error.
Instead make a use of Any extension method if you are looking for whether exist in the collection kind of thing..
var x = AccountSummeriesResponse.items.Where(wp => wp.webProperties.Any(p => p.profiles.Any(a => a.id == profile ))).FirstOrDefault();

Convert this LINQ to Lambda Expression?

I have a LINQ, it works fine. My question is: how to convert it to Lambda Expression?
var searchResults = from study in dataContext.Studies
join location in dataContext.Locations
on study.LocationID equals location.LocationID
join doctorLocation in dataContext.DoctorLocations
on location.LocationID equals doctorLocation.LocationID
join doctor in dataContext.Doctors
on doctorLocation.DoctorID equals doctor.DoctorID
where doctor.DoctorID == doctorId
select study;
I think LINQ is more natural to me (similar to SQL script). However, in this case, I just want to convert it to Lambda Expression, but I could not make it work.
I got stuck at:
var searchResults = dataContext.Studies.Where(x =>
x.Location.DoctorLocations.FirstOrDefault() != null &&
x.Location.DoctorLocations.FirstOrDefault().DoctorID == doctorId);
This only works for FirstOrDefault. Since there are multiple DoctorLocations, I do not how to write this one.
Try this:
var searchResults = dataContext.Studies.Where(x =>
x.Location != null
&& x.Location.DoctorLocations.Any(dl => dl.DoctorID == doctorId));
you will get all Studies related to at least one DoctorLocation with DoctorID equals doctorId
var searchResults = dataContext.Studies
.Include(x => x.Locations)
.Include(x => x.DoctorLocations)
.Include(x => x.Doctors)
.Where(x => x.[InheritedPathToDoctor].DoctorId == id)
.Select(x => x.[InheritedPathToStudy].Study)
.FirstOrDefault() OR .ToList()
I have made a lot of assumptions here as to how you have set up your context. I've assumed it's a relational database and therefore the includes simply means it returns all data. I haven't tested it though so there are probably a few errors.
You require an include for every class and the where is pretty self explanatory.

Can I do a EF statement Where( c => c.NameStr == (is element in list<string> ) )?

I want to do a Where statement but check to see if a field member matches an item in a list of strings instead of just a string. My entities are autogenerated from the DB and stored in the .edmx file.
//selectedAgencys is a List<string>
List<v_MapCrimeData> list = ent.v_MapCrimeData
.Where(c => c.AgencyName == (element in list selectedAgencys));
You want to see if the list contains the field, so you can use the Enumerable.Contains
nt.v_MapCrimeData.Where(c => selectedAgencys.Contains(c.AgencyName))
Since you indicated you're using Linq to Entities you might want to try a join.
List<v_MapCrimeData> list = v_MapCrimeData.Join(
selectedAgencies,
c => c.AgencyName, //key selector for v_MapCrimeData
a => a, //key selected for selectedAgencies
(c, a) => c).ToList(); //result selector (i.e. return the v_MapCrimeData)
Try
List<v_MapCrimeData> list = (from c in ent.v_MapCrimeData
from x in selectedAgencys
where x == c.AgencyName
select c).ToList();
If you need to ignore case,
nt.v_MapCrimeData.Where(c => selectedAgencys.Any(a => a.Equals (c.AgencyName, StringComparison.OrdinalIgnoreCase))
.Where(i => listocheckagainst.Contains(i.valuetoBeChecked))
Edit: spent time signing up to SO and someone else answered

LINQ - SELECT DISTINCT with NOT IN

I'm have a SQL statement which I am trying to transform in a LINQ statement...
SELECT DISTINCT mc.*
FROM ManufractorCategories mc
WHERE mc.Active = 'true'
AND mc.Folder = 'false'
AND (mc.Id not in (SELECT Category_id FROM Manufractor_Category
WHERE Manufractor_id = 3));
That's my last, not working LINQ statement
(IQueryable<object>)db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder }).Except(db.Manufractor_Categories.Where(t => t.Manufractor_id == id).Select(t => new { t.Category_id })).Distinct();
I've tried the whole Sunday on that, but the Except statement won't work.
Thanks in advances for any help!
The Except method requires two sets of the same type - this means that you would have to select objects of type ManufractorCategory in the nested query as well as in the outer query - then it would select all categories that are in the first one and not in the second one.
An easier alternative is to use the Contains method to check whether the current ID is in a list of IDs that you want to filter. The following should work:
var q =
db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder })
.Where(o =>
!db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
.Distinct();
And a simplified version using query syntax:
var q =
from o in db.ManufractorCategories
where o.Active == active && o.Folder == folder &&
db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
select new { i.Id, i.Folder };
The Except statement is going to get a list of objects with the Category_id property. However, you're query has a result that contains objects with the Id and Folder properties. The query will most likely be unable to see where these objects are equal, and so, the Except clause won't take effect.

Categories