Question

I have a performance problem I can't solve. If you look at the code below it works fine, but when I change the OrderByDescending(x => x.ID) so it uses the paramater sortOrder instead, it gives me a timeout.

Im calling the function with the same lambda expression that I supplied in the OrderByDescending.

m_DAL.GetPastes(page, userName, x => x.ID).ToList<Paste>();

This works but i want to be able to pass the sortOrder as a parameter.

    public IEnumerable<Paste> GetPastes(int page, string username, Func<Paste, object> sortOrder)
    {
        return this.Filter<Paste>(x => x.Expires == null || x.Expires > DateTime.UtcNow)
            .Where(x => x.AccessMode.Key == 1 || (x.AccessMode.Key == 2 && x.User.UserName == username))
            .Where(x => x.CaptchaOK == true || (x.AccessMode.Key == 2 && x.User.UserName == username))
            .OrderByDescending(x => x.ID)
            .Skip(m_pagesize * page)
            .Take(m_pagesize)
            .ToList<Paste>();
    }

This is giving me a timeout:

public IEnumerable<Paste> GetPastes(int page, string username, Func<Paste, object> sortOrder)
    {
        return this.Filter<Paste>(x => x.Expires == null || x.Expires > DateTime.UtcNow)
            .Where(x => x.AccessMode.Key == 1 || (x.AccessMode.Key == 2 && x.User.UserName == username))
            .Where(x => x.CaptchaOK == true || (x.AccessMode.Key == 2 && x.User.UserName == username))
            .OrderByDescending(sortOrder)
            .Skip(m_pagesize * page)
            .Take(m_pagesize)
            .ToList<Paste>();
    }

How can I resolve this problem? Is it the definition of the function that is wrong?

Was it helpful?

Solution

If you use just Func<Paste, object> - you get overload of OrderBy that retrieves all entites to memory and orders them. For getting more performance I would recommend you using Expression<T> which would be translated in SQL and run on db side:

EDIT: Also you could make your method generic for omiting this:

NotSupportedException: Unable to cast the type 'System.Int32' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.

public IEnumerable<Paste> GetPastes<TOrderKey>(int page, string username, 
                   Expression<Func<Paste, TOrderKey>> sortOrder)
{
    // code from the question
}

Note that the way you call this method won't change because of type inference:

m_DAL.GetPastes(page, userName, x => x.ID).ToList<Paste>();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top