Reputation: 392
I want to make a query using EF
and my query looks like the following
var users = MyDbc.AspNetUsers.Where
(
d =>
(
d.UserPlans.Where(m => m.IsActive == 1).FirstOrDefault().PlanId == 2
||
(d.UserPlans.Where(m => m.IsActive == 1).FirstOrDefault().PlanId == 3
&& d.UserGroups.FirstOrDefault().Group.AdminId == d.Id)
)
);
How can I avoid querying UserPlans twice?
in SQL
I would write the following
SELECT * FROM AspNetUsers U INNER JOIN UserPlan UP ON U.Id = UP.UserId
WHERE UP.IsActive = 1
AND (
PlanId=2 OR (PlanId=3 AND EXISTS(SELECT 1 FROM [Group] WHERE AdminId=U.Id ))
)
Upvotes: 4
Views: 382
Reputation: 7526
Just use built-in query syntax:
var users = from user in MyDbc.AspNetUsers
from plan in user.UserPlans.Where(m=>m.IsActive == 1)
where plan.PlanId == 2 || plan.PlanId == 3 && ...
It is more agile in terms of selecting query time variables. And it is MUCH more readable when your query goes large. For simple queries I personally still use pure LINQ extensions.
PS
As @juharr mentioned in comment, your query will probably be optimized by SQL provider, so you are good with performance, but readability and fault-resistance of your query is indeed poor.
Upvotes: 4
Reputation: 813
I think your looking for this. You can just do both checks straight in the first where.
d.UserPlans.Where(m => m.IsActive == 1 &&
(m.PlanId == 2 || (m.PlandId == 3 &&
d.UserGroups.FirstOrDefault().Group.AdminId == d.I)))
Upvotes: 1
Reputation: 519
I would probably pack this into a view or stored procedure (if you need dynamic ids) and load that separately.
CREATE VIEW Users
AS
SELECT * FROM AspNetUsers U INNER JOIN UserPlan UP ON U.Id = UP.UserId
WHERE UP.IsActive = 1
AND (
PlanId=2 OR (PlanId=3 AND EXISTS(SELECT 1 FROM [Group] WHERE AdminId=U.Id ))
)
GO
and then call it in c#...
var users = MyDbc.Users.ToList();
... like that.
Upvotes: 1