views:

73

answers:

2

I am using Linq to Sql as my ORM and I have a list of Ids (up to a few thousand) passed into my retriever method, and with that list I want to grab all User records that correspond to those unique Ids. To clarify, imagine I have something like this:

List<IUser> GetUsersForListOfIds(List<int> ids)
{
        using (var db = new UserDataContext(_connectionString))
        {
            var results = (from user in db.UserDtos
                           where ids.Contains(user.Id)
                           select user);

            return results.Cast<IUser>().ToList();
        }
}

Essentially that gets translated into sql as

select * from dbo.Users where userId in ([comma delimmited list of Ids])

I'm looking for a more efficient way of doing this. The problem is the in clause in sql seems to take too long (over 30 seconds).

Any thoughts?

A: 

Will need more information on your database setup like index's and type of server (Mitch Wheat's post). Type of database would help as well, some databases handle in clauses poorly.

From a trouble shooting standpoint...have you isolated the time delay to the sql server? Can you run the query directly on your server and confirm it's the query taking the extra time?

Select * can also have a bit of a performance impact...could you narrow down the result set that's being returned to just the columns you require?

edit: just saw the 'view comment' that you added...I've had problems with view performance in the past. Is it a materialized view...or could you make it into one? Recreating the view logic as a stored procedure may aslo help.

M.E.
MS SQL Server 2008, unfortunately my view does not have any indexes because of the constraints the db has on placing indexes on views. My view (it's an old one from years back), is very convoluted and disgusting, some of the logic that goes on in the view enforces a constraint on the db to not allow me to apply indexes. And yes, I have isolated it running the query with an in clause in sql to be the issue. IN is pretty inefficient, especially with a few thousand parameters being passed to it. I was hoping someone would know some linq to sql that would get me around this issue..
Justin Williams
I don't know linq to sql well enough to be certain, but I'd have a hard time seeing it being able to run the query quicker than directly against the database takes. I think your comment @brad is right...make a stored proc and try to limit the information returned to be specific to your needs here. Might be best to put the ID's that are in the 'in' statement here into a temp table and let the stored proc work from that table instead of trying to pass a giant 'in' variable to the proc
M.E.
Yeah, unfortunately that's how i have it solved for the time being (a stored proc). I'll leave this open still in case if that one linq to sql guru comes out and has a good idea for me. Thank you so much for your help and quick response :)
Justin Williams
@Justin maybe you should share the sp you used in an update to the question, that way is more likely someone might come with something similar in linq
eglasius
A: 

Have you tried converting this to a list, so the application is doing this in-memory? i.e.:

List<IUser> GetUsersForListOfIds(List<int> ids)
{
        using (var db = new UserDataContext(_connectionString))
        {
            var results = (from user in db.UserDtos.ToList()
                           where ids.Contains(user.Id)
                           select user);

            return results.Cast<IUser>().ToList();
        }
}

This will obviously be memory-intensive if this is being run on a public-facing page on a hard-hit site. If this still takes 30+ seconds though in staging/development, then my guess is that the View itself takes that long to process -OR- you're transferring 10's of MB of data each time you retrieve the view. Either way, my only suggestions are to access the table directly and only retrieve the data you need, rewrite the view, or create a new view for this particular scenario.

Keith
@Keith: That was definitely an option until I realized how many records the view has, way too many to convert to in-memory, unfortunately. Thanks though!
Justin Williams