var companytoexclude = from c in db.Companies
from p in c.Projects
where p.ProjectEndDate == null
select c;
var list = from m in db.Members.Include("Companies.Projects.Experiences")
where m.MemberId == id
select m;
how do I exclude companies that are in companytoexclude in list?
Member have many company
company have many project
project have many experiences
K I kind of solved it.
So what I did is just add in
foreach (Company c in companytoexclude )
{
list .First().Companies.Remove(c);
}
so is there a easier to show this?
I want the member with list of companies, not just companies.
some data
Member
MemberId Name
2011 Jet
Company
CompanyId MemberId CompanyName
18 2011 Company1
29 2011 Company2
ProjectId CompanyId ProjectName ProjectEndDate
1 29 Project1 2008-08-01 00:00:00.000
2 29 Project2 2009-08-01 00:00:00.000
3 18 Project3 NULL
now I want it to return everything but company1 and project3
How about:
var list = from m in db.Members.Include("Companies.Projects.Experiences")
where m.MemberId == id
where !m.Companies.Intersect(companiesToExclude).Any()
select m;
That will only return members which don't include any companies which you're trying to exclude.
Mind you, given that you're specifying a MemberId, I'd pretty much only expect one result anyway... it's unclear what you're trying to do.
If you want all the companies from that single member except the companies to exclude, it's easy:
var member = db.Members.Include("Companies.Projects.Experiences")
.Single(m => m.MemberId == id);
var companies = member.Companies.Except(companiesToExclude);
If that's not what you're after, please clarify your question.
Also note that your companiesToExclude query may well not be right to start with. Are you trying to exclude all companies with any project with a null end date? If so, you want:
var companiesToExclude = db.Companies
.Where(c => c.Projects
.Any(p => p.ProjectEndDate == null))
Related
Let’s assume I have three tables in my database:
Authors(PK Id, AuthorName)
Books(PK Id, BookName)
Authors_Books(FK BookId, FK AuthorId)
I need to write a method which passes in a parameter int[] authorsIds and returns all books (Id, BookName, list of authors of this book) if it was written by any author whose Id contains in int[] authorsIds parameter.
I need LINQ query (query method).
I really need a help. Appreciate your help very much.
var int[] authors = { 1, 2, 3 };
var books = from book in books
where book.Authors.Any(x => authors.Contains(x.AuthorId))
select book;
PS: I assume book.Authors is your reference to Authors_Books table (or maybe has a different name).
this answer is based on the exact structure without considering that A obj has B in its structure
var book = from b in books
where book.Id in ( from ab in AuthersBooks
where selectedAuthers.contains(ab.AutherId)
select ab.bookId ) //now we have books that are authered by one of the selected authers
select new { BookId = b.Id, // now we create an anonymos object to contain any info we need
BookName = b.Name,
BookAuthers = (from a in authers
join ab in AuthersBooks
on a.Id == ab.AuthersId
where ab.bookid == b.Id
select a)
this will propably have syntax errors and after correcting you may get an error about multiple threads which already has an answer here
I guess there must be an easy way, but not finding it. I would like to check whether a list of items, appear (completely or partially) in another list.
For example: Let's say I have people in a department as List 1. Then I have a list of sports with a list of participants in that sport.
Now I want to count, in how many sports does all the people of a department appear.
(I know some tables might not make sense when looking at it from a normalisation angle, but it is easier this way than to try and explain my real tables)
So I have something like this:
var peopleInDepartment = from d in Department_Members
group d by r.DepartmentID into g
select new
{
DepartmentID = g.Key,
TeamMembers = g.Select(r => d.PersonID).ToList()
};
var peopleInTeam = from s in Sports
select new
{
SportID = s.SportID,
PeopleInSport = s.Participants.Select(x => x.PersonID),
NoOfMatches = peopleInDepartment.Contains(s.Participants.Select(x => x.PersonID)).Count()
};
The error here is that peopleInDepartment does not contain a definition for 'Contains'. Think I'm just in need of a new angle to look at this.
As the end result I would like print:
Department 1 : The Department participates in 3 sports
Department 2 : The Department participates in 0 sports
etc.
Judging from the expected result, you should base the query on Department table like the first query. Maybe just include the sports count in the first query like so :
var peopleInDepartment =
from d in Department_Members
group d by r.DepartmentID into g
select new
{
DepartmentID = g.Key,
TeamMembers = g.Select(r => d.PersonID).ToList(),
NumberOfSports = Sports.Count(s => s.Participants
.Any(p => g.Select(r => r.PersonID)
.Contains(p.PersonID)
)
)
};
NumberOfSports should contains count of sports, where any of its participant is listed as member of current department (g.Select(r => r.PersonID).Contains(p.PersonID))).
I have the following LINQ query using EF5 and generic repository, unit of work patterns to a SQL Server 2008 db
var countriesArr = GetIdsFromDelimStr(countries);
var competitionsArr = GetIdsFromDelimStr(competitions);
var filterTeamName = string.Empty;
if (teamName != null)
{
filterTeamName = teamName.ToUpper();
}
using (var unitOfWork = new FootballUnitOfWork(ConnFooty))
{
// give us our selection of teams
var teams =
(from team in
unitOfWork.TeamRepository.Find()
where ((string.IsNullOrEmpty(filterTeamName) || team.Name.ToUpper().Contains(filterTeamName)) &&
(countriesArr.Contains(team.Venue.Country.Id) || countriesArr.Count() == 0))
select new
{
tId = team.Id
}).Distinct();
// give us our selection of contests
var conts = (
from cont in
unitOfWork.ContestRepository.Find(
c =>
((c.ContestType == ContestType.League && competitionsArr.Count() == 0) ||
(competitionsArr.Contains(c.Competition.Id) && competitionsArr.Count() == 0)))
select new
{
contId = cont.Id
}
).Distinct();
// get selection of home teams based on contest
var homecomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.HomeTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.HomeTeam.Id,
teamName = fixt.HomeTeam.Name,
countryId = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Id : 0,
countryName = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// get selection of away teams based on contest
var awaycomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.AwayTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.AwayTeam.Id,
teamName = fixt.AwayTeam.Name,
countryId = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Id : 0,
countryName = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// ensure that we return the max competition based on id for home teams
var homemax = (from t in homecomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
// ensure that we return the max competition based on id for away teams
var awaymax = (from t in awaycomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
var filteredteams = homemax.Union(awaymax).OrderBy(t => t.teamName).AsQueryable();
As you can see we want to return the following format which is passed across to a WebAPI so we cast the results to types we can relate to in the UI.
Essentially what we are trying to do is get the home and away teams from a fixture, these fixtures have a contest which relates to a competition. We then get the highest competition id from the grouping and then this is returned with that team. The country is related to the team based on the venue id, when I was originally doing this i had problems figuring out how to do OR joins in linq which is why i split it down to getting home teams and away team and then grouping them based on competition then unioning them together.
An idea of current table size is fixtures has 7840 rows, teams has 8581 rows, contests has 337 rows and competitions has 96 rows. The table that is likely to increase rapidly is the fixture table as this is related to football.
The output we want to end up with is
Team Id, Team Name, Country Id, Country Name, Competition Id, Competition Name
Using no filtering this query takes on average around 5 secs, just wondering if anybody has any ideas/pointers on how to make it quicker.
thanks in advance Mark
I can't judge whether it will speed up things, but your homemax and awaymax queries could be
var homemax = from t in homecomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
var awaymax = from t in awaycomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
Further, as you are composing one very large query it may perform better when you cut it up in a few smaller queries that fetch intermediary results. Sometimes a few more roundtrips to the database perform better than one very large query for which the database engine can't find a good execution plan.
Another thing is all these Distinct()s. Do you always need them? I think you can do without because you are always fetching data from one table without joining a child collection. Removing them may save a bunch.
Yet another optimization could be to remove the ToUpper. The comparison is done by the database engine in SQL and chances are that the database has a case-insensitive collation. If so, the comparison is never case sensitive even if you'd want it to be! Constructs like Name.ToUpper cancel the use of any index on Name (it is not sargable).
I have a list like this:
List people
age name
1 bob
1 sam
7 fred
7 tom
8 sally
I need to do a linq query on people and get an int of the number distinct ages (3)
int distinctAges = people.SomeLinq();
how?
how?
Select out the age, then use Distinct and Count.
var ages = people.Select( p => p.Age ).Distinct().Count()
Or you could use GroupBy and Count
var ages = people.GroupBy( p => p.Age ).Count();
Download LinqPad and give these simple linq / lambda queries yourself. Its very easy to compare the SQL and equivalent Linq / lambda result set.
You would start with
select Age, Name
from People
group by Age, Name
Then open another tab
var ages = (from p in Peoples
group p by p.Age into g
select g);
ages.Dump();
Then open another tab
var ages = Peoples.GroupBy(p => p.Age);
ages.Dump();
I have the following expression in linq (its a join) and i am selecting into "J" because i need to use J later (currently i just selecting J but once i have this fixed i plan on use J within another subquery after)
But it won't let me supply a where using the "V" side hence v.IdOFfice is invalid.
I have tried swapping around the joins and that what happens i can't use the "GVT"..
WIth specifying the where it works perfect but i need to specify 2 wheres that are present in the 2 tables ... hence IdOffice and IdTariff are in there own tables .. they are not both ....
(from gvt in Tariffs
join v in Items
on gvt.IdGroupItem equals v.IdGroupItem
into j
where v.IdOffice == 1 && gvt.IdTariff == 111
select j).Take(50)
Probably something silly, it appears the table specified after the join i am not able to use in the where?
Any ideas?
Thanks
This is basically what i am trying to achieve
from gvt in Tariffs
join v in Items
on gvt.IdGroupItem equals v.IdGroupItem
into j
where v.IdOffice == 1 && gvt.IdTariff == 111
select new
{
id = v.IdItem
Tariff = from j
{
test = j.TariffDesc,
test1 = j.TariffPrice
}
basicaly i end up with 1 record with Id and a field which as many tariffs inside - if this makes sense?
}
Query working great,
it would be nice to be able to use an extension method (c#) like so ... is this possible so i can dynamically set tariff ... so for example i do the query and i have an extension method (which i already use on simple queries) like so
public static IQueryable<Models.ItemTariffCol> WithTariffId(this IQueryable<Models.ItemTariffCol> qry, int tariffId)
{
return from t in qry
where t.IdTarifa == tariffId
select t;
}
this makes it very extensible ? If its a normal where i can do this but the query isn't in the where
Thank you.
You're doing a group join here, since you're using into. This means that for every gvt, you have not one Item, but possibly several (or none). The list of all items is stored in j, as an IEnumerable<Item>. If you want to select all tariffs for which there's at least one item with IdOffice == 1, then you can do it like this:
from gvt in Tariffs
join v in Items
on gvt.IdGroupItem equals v.IdGroupItem
into j
where gvt.IdTariff == 111 && j.Any(v => v.IdOffice == 1)
...
After the answer edit, it seems that you've started from the wrong direction as well - so far as I can see, you want a list of tariffs for every item, not the list of items for every tariff. For that, you need to reverse your join:
from item in Items
join tariff in Tariffs
on item.IdGroupItem equals tariff.IdGroupItem
into tariffs
where item.IdOffice == 1
select new
{
Id = item.IdItem,
Tariffs = from tariff in tariffs
where tariff.IdTariff == 111
select new { tariff.TariffDesc, tariff.TariffPrice }
}
Or you could filter tariffs right in the join:
from item in Items
join tariff in (from t in Tariffs where t.IdTariff == 111 select t)
on item.IdGroupItem equals tariff.IdGroupItem
into tariffs
where item.IdOffice == 1
select new
{
Id = item.IdItem,
Tariffs = from tariff in tariffs
select new { tariff.TariffDesc, tariff.TariffPrice }
}