Reputation: 779
I have a controller as below, and it takes too long load the data. I am using contains and tolist() methods. And i have heard about low performance of toList() method.
How can i change this approach with better coding for performance.
public List<decimal> GetOrgSolution()
{
//Need to use USER id. but we have EMPNO in session.
var Users = db.CRM_USERS.Where(c => c.ID == SessionCurrentUser.ID || RelOrgPerson.Contains(c.EMPNO.Value)).Select(c => c.ID);
//Get the organization list regarding to HR organization
var OrgList = db.CRM_SOLUTION_ORG.Where(c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value)).Select(c => c.ID).ToList();
//Get related solutions ID with the OrgList
List<decimal> SolutionList = db.CRM_SOLUTION_OWNER.Where(p => OrgList.Contains(p.SOLUTION_ORG_ID.Value)).Select(c => (decimal)c.SOLUTION_ID).Distinct().ToList();
return SolutionList;
}
Upvotes: 1
Views: 3845
Reputation: 134045
Unless the lists you're working with are really huge, it's highly unlikely that calling ToList
is the major bottleneck in your code. I'd be much more inclined to suspect the database (assuming you're doing LINQ-to-SQL). Or, your embedded Contains
calls. You have, for example:
db.CRM_SOLUTION_ORG..Where(
c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value))
So for every item in db.CRM_SOLUTION_ORG
that fails the test against SessionCurrentUser
, you're going to do a sequential search of the Users
list.
Come to think of it, because Users
is lazily evaluated, you're going to execute that Users
query every time you call Users.Contains
. It looks like your code would be much more efficient in this case if you called ToList()
on the Users
. That way the query is only executed once.
And you probably should keep the ToList()
on the OrgList
query. Otherwise you'll be re-executing that query every time you call OrgList.Contains
.
That said, if Users
or OrgList
could have a lot of items, then you'd be better off turning them into HashSet
s so that you get O(1) lookup rather than O(n) lookup.
But looking at your code, it seems like you should be able to do all of this with a single query using joins, and let the database server take care of it. I don't know enough about Linq to SQL or your data model to say for sure, but from where I'm standing it sure looks like a simple joining of three tables.
Upvotes: 2
Reputation:
You might be able to speed this up by dropping the ToList()
from the orglist query. This uses deferred execution, rather than pulling all the records for the org list. However, if there is no match on the query that calls Contains()
, it will still have to load everything.
public List<decimal> GetOrgSolution()
{
//Need to use USER id. but we have EMPNO in session.
var Users = db.CRM_USERS.Where(c => c.ID == SessionCurrentUser.ID || RelOrgPerson.Contains(c.EMPNO.Value)).Select(c => c.ID);
//Get the organization list regarding to HR organization
var OrgList = db.CRM_SOLUTION_ORG.Where(c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value)).Select(c => c.ID);
//Get related solutions ID with the OrgList
List<decimal> SolutionList = db.CRM_SOLUTION_OWNER.Where(p => OrgList.Contains(p.SOLUTION_ORG_ID.Value)).Select(c => (decimal)c.SOLUTION_ID).Distinct().ToList();
return SolutionList;
}
Upvotes: 3