Reputation: 923
So I am using a table twice in my query, and I dont know of another way to only use it once. Here is my query:
var result = (from t1 in (from t1 in db.Students.Where(en => en.Progress == MyEnum.Accepted).GroupBy(en => en.Class).AsEnumerable()
join t2 in dbOther.Classes on t1.Key equals t2.Class
select t2)
join t3 in (db.Students).AsEnumerable() on t1.Class equals t3.Class into t4
select new
{
ClassNum = t1.Class,
StartDate = t1.StartDate,
Weeks = t1.Weeks,
Accepted = t4.Where(e => e.Progress == MyEnum.Accepted).Count(),
NotAccepted = t4.Where(e => e.Progress < MyEnum.Accepted).Count()
}).ToList();
I need to only get classes that have students in the accepted state. Then I want to get the classes and the count of its entire roster, even the students that are not accepted. Is there a better way to do this? It seems like reading from the same table twice is not the fastest way to do this.
Thank you for the help.
Upvotes: 0
Views: 111
Reputation: 78598
Unless you're really simplifying the query here, you don't really need to hit dbOther
to find out what classes has any students in the Accepted state. That information is in db
.
var studentCountPerClass = (from s in db.Students
group s by s.Class into studentsByClass
where studentsByClass.Any(x => x.Progress == MyEnum.Accepted)
select new
{
ClassNum = studentsByClass.Key,
Accepted = studentsByClass.Count(s => s.Progress == MyEnum.Accepted),
NotAccepted = studentsByClass.Count(s => s.Progress < MyEnum.Accepted),
})
.ToList();
var classCodes = studentCountPerClass.Select(x => x.ClassNum).ToList();
var classData = (from c in dbOther.Classes
where classCodes.Contains(c.Class)
select new {
c.Class,
// Any other data you want about the class
})
Upvotes: 1
Reputation: 726929
First, fetch information about student enrollment from db.Students
table:
var stats = db.Students
.GroupBy(en => en.Class)
.Select(g => new {
Class = g.Key
, Accepted = g.Count(en => en.Progress == MyEnum.Accepted)
, NotAccepted = g.Count(en => en.Progress < MyEnum.Accepted)
})
.Where(g => g.Accepted != 0)
.ToList();
Next, fetch classes from the other database:
var classIds = stats.Select(en => en.Class).ToList();
var classes = dbOther.Classes.Where(c => classIds.Contains(c.Class)).ToList();
Finally, join the two into the result:
var result = (from s in stats
join c in classes on c.ClassId = s.ClassId
select new {
ClassNum = c.Class
, c.StartDate
, c.Weeks
, s.Accepted
, s.NotAccepted
}).ToList();
Upvotes: 1
Reputation: 2078
Instead of USING ". Enumerable()" over the student db object, use Querable. This will create an expression which gets evaluated at database level rather than fetching entire student table first and then doing the comparison.
Check this for details Returning IEnumerable<T> vs. IQueryable<T>
Just to try, set the profiler and see the generated queries for both Enumerable vs Queryable.. The difference will get illustrated there.
Entity framework is easiest showcased with differences in execution with both these methods. Also the simplest ORM to support these functions.
Upvotes: 0