I have the following two tables
Groups
Id (int)
People
Id (int)
GroupId (int, Groups.Id)
IsSelected (bit)
This will return all Groups with all their members(People) in a single query
var grps = myDatabase.Groups.Include("People");
How can I write a single query that will return all Groups with People who has been selected(IsSelected = true)?
let me know if this works
var grps = myDatabase.Groups.Select(g=> new { g, people = g.People.Where(p=>p.IsSelected)});
You will want to use the 'join' method, like this:
(from g in myDatabase.Groups
join p in myDatabase.People on g.Id equals p.GroupId
where p.IsSelected == true
select g);
This will give you all groups where there are people selected.
OR check out .Where()
Something like
var grps = myDatabase.Groups.Include("People").Where(x => x.IsSelected);
//x => !x.IsSelected for false
Related
There seem to be lots of questions about SQL to LINQ, but I can't seem to find examples with joined tables and grouping; specifically with a need to get data from multiple tables.
Take this simple SQL:
SELECT
s.showId, s.showName, v.venueName, Min(dateTime) startDate
FROM
shows s
INNER JOIN venues v ON s.venueId = v.venueId
INNER JOIN showDates d ON s.showId = d.showId
GROUP BY
s.showId
The best I can come up with is the following
var ungrouped = (
from s in db.Shows
join v in db.Venues on s.VenueId equals v.VenueId
join d in db.ShowDates on s.ShowId equals d.ShowId
select new { s, v, d }
).ToList();
var grouped = (
from s in ungrouped
group s by s.s.ShowId into grp
select new
{
showId = grp.Key,
name = (from g in grp select g.s.showName).FirstOrDefault(),
venue = (from g in grp select g.v.VenueName).FirstOrDefault(),
startDate = grp.Max(g => g.d.DateTime)
}
);
This works but it feels messy. I don't like:
It being split into two statements
Having to repeatedly write (from g in grp select ...).FirstOrDefault()
Bits like s.s.ShowId
How its vastly more lines of code than the SQL
This example is a simple one, it only gets worse when I have 5+ tables to join and 10+ columns to select.
Question: Is this the best way to do this, and I should just accept it; or is there a better way to write this query?
I am not sure if you are looking for something like this but it's a bit cleaner, it's not split in 2 statements and you might find it helpful. I couldn't use a dbcontext so I used lists to make sure the syntax is correct.
var res = Shows.Join(Venues,
show => show.VenueID,
venue => venue.VenueID,
(show, venue) => new { show, venue })
.Join(ShowDates,
val => val.show.ShowID,
showdate => showdate.ShowID,
(val, showDate) => new { val.show, val.venue, showDates = showDate })
.GroupBy(u => u.show.ShowID)
.Select(grp => new
{
showId = grp.Key,
name = grp.FirstOrDefault()?.show.showName,
venue = grp.FirstOrDefault()?.venue.VenueName,
startDate = grp.Max(g => g.showDates.DateTime)
});
we need to now realation beetwen them one to one or one to many , but not too far from this answer.
var GrouppedResult = Shows.Include(x=>x.Veneu).Include(x=>x.ShowDates)
.Where(x=>x.Veneu.Any()&&x.ShowDates.Any())
.GroupBy(x=>x.ShowId)
.Select(x=>///anything you want);
or
from show in Shows
join veneu in Veneu on veneu.VeneuId equals show.VeneuId
join showDates in ShowDates on showDates.ShowId=show.ShowID
group show by show.Id into grouppedShows
select new { ///what you want };
I'm trying to do something very simple.
I have two tables in my database that I would like to query using linq.
Table of Books, and table of GenreTypes. The result of this query would go to my web Api.
Here is a code snippet:
public List<BooksChart> GetBooksChart()
{
var results = from b in _dbcontext.Books
join g in _dbcontext.GenreTypes
on b.GenreTypeId equals g.Id
group g by g.Name into n
select (z => new BooksChart
{
category_name = n.Key,
value = n.Count()
}).ToList();
return results;
}
public class BooksChart
{
public string category_name;
public int value;
}
The results of the grouping "n" I would like to store them in BooksChart class to construct the Api.
This code is not compiling.
Previously, I was querying only one table of Books which I have divided into Books and GenreTypes.
My previous working code for querying Books was :
var results = _dbcontext
.Books
.GroupBy(x => x.GenreType)
.Select(z => new BooksPieChart
{
category_name = z.Key,
value = z.Count()
}).ToList();
return results;
EDIT
What I want to achieve in SQL is the following:
select count(*), g.Name
from books b, GenreTypes g
where b.GenreTypeId = g.Id
group by g.Name;
You are mixing the two syntax options of query and method. For query syntax you need to do the projection (select) like this:
return (from b in _dbcontext.Books
join g in _dbcontext.GenreTypes on b.GenreTypeId equals g.Id
group g by g.Name into n
select new BooksChart {
category_name = n.Key,
value = n.Count()
}).ToList();
The format of (z =>....) is the declaration of the labmda passed to the Select method.
Site notes:
As #Rabbi commented, since you are using EF, consider properly defining navigation properties. It will make querying simpler.
Side note for the sql - consider using joins instead of multiple tables in the from: INNER JOIN ON vs WHERE clause
The parentheses must surround the whole query, like so:
var results = (from b in _dbcontext.Books
join g in _dbcontext.GenreTypes
on b.GenreTypeId equals g.Id
group g by g.Name into n
select new BooksChart
{
category_name = n.Key,
value = n.Count()
}).ToList();
The compilation error is due to this (z => which is not needed at all.
I need to get NewsImage field and list of categories Ids that associated with the news in Many to Many relationship ... but it gives me error:
The type of one of the expressions in the join clause is incorrect.Type inference failed in the call to 'Join'.
My code looks like this
var Result1 = (from c in db.News
join d in db.Categories
on c.NewsId equals d.News.Select(l => l.NewsId)
where c.NewsId == 1
select new { c.NewsImagePath, d.CategoryId }).ToList();
Assuming you have a navigation property defining the n-n relation I would write:
var result = db.News
.Where(x => x.NewsId == 1)
.SelectMany(x => x.Categories,
(news, category) => new { news.NewsImagePath, category.CategoryId })
.ToList();
The problem is inside the on statement.
on c.NewsId equals d.News.Select( l => l.NewsId )
The Select on the right-hand side will return a IEnumerable of news, which is not what you want.
Something like this would technically work:
on c.NewsId equals d.News.Select( l => l.NewsId ).FirstOrDefault()
But it does not make sense logically.
I suspect the whole query should be built differently. I think you want to join when the category list of news contains the news item. In that case, you can't use the join statement, it would look somewhat like this:
from n in db.News
from c in db.Categories
where c.News.Select( ne => ne.NewsId ).Contains( n.NewsId )
select new { n.NewsImagePath, c.CategoryId }
I'm trying to sorting groups by active players...
In this case, the first group contains the biggest players inside:
List<Group> groups = tournament.Groups.OrderByDescending(o => o.Players.Count).ToList();
I have to add an filter that will count only active players, Something like this:
if (o.Players[index].Active == true)
count Players[index] into o.Players.Count
Can someone help me with the syntax?
you can use this :
List<Group> groups = tournament.Groups
.OrderByDescending(o => o.Players.Count(P => P.Active)).ToList();
If you want to filter on active players only, you can hand over a predicate in the Count extension method:
List<Group> groups = tournament
.Groups
.OrderByDescending
(o => o.Players.Count(p => p.Active))
.ToList();
You may like to show in the result how many actual players are, not only sorting by them
var query = from g in tournament.Groups
let activePlayers = g.Players.Count(p=>p.Active)
orderby activePlayers descending
select new {Group = g, ActivePlayers = activePlayers};
Here's my query.
var query = from g in dc.Group
join gm in dc.GroupMembers on g.ID equals gm.GroupID
where gm.UserID == UserID
select new {
id = g.ID,
name = g.Name,
pools = (from pool in g.Pool
// more stuff to populate pools
So I have to perform some filtering, but when I attempt to filter
var filter = query.Where(f => f.pools.[no access to list of columns]
I can't access any of the items within "pools". Does anyone know how I'm able to access that?
What I'd like to do is this:
var filterbyGame = query.Where(f = > f.pools.GameName == "TestGame");
Let me know if that's even possible with thew ay I have this setup.
Thanks guys.
In your query you can't do Where(f => f.pools.GameName)
because f is an IEnumerable<>
Something like this should work:
Where(f => f.pools.Any(p => p.GameName == "TestGame"))
pools is an enumeration, not a single instance. That's why you're not getting column names.
You need to change your filter to something like:
var filterByGame = query.Where(f => f.pools.Any(p => p.GameName == "TestGame"));