Speed up query to rank team sales by aggregating data from two databases On my machine it runs in about 60 seconds and about 2-3 minutes live.

The criteria needed are:


Current month only (from first of month until current day)
I need the rank of the currently logged in person based on total sales.
I have two tables across two databases where this data is to be gathered:


Database 1: ProPit_User table (this houses the logged in users).
Database 2: This houses the sales in the Orders table.  

Both tables will be linked on the SalesRepID column.
There are around around 352 users in the ProPit_User table.
There are a lot of orders in the orders table.


This code does what I need it to do; it is just dreadfully slow.

public static int GetNationalRank(int teamId, int CurrentUserId)
{
    List&lt;ProPit_User&gt; lstProPit_User = new List&lt;ProPit_User&gt;();
    List&lt;TeamSales&gt; lstTeamSales = new List&lt;TeamSales&gt;();
    int currentUserRank = 0;

    using (ProsPitEntities ppdb = new ProsPitEntities())
    using (TraegerEntities db = new TraegerEntities())
    {
        lstProPit_User = ppdb.ProPit_User.Where(x =&gt; x.SalesRepID != null).ToList();

        foreach (var user in lstProPit_User)
        {

            var strStartDate = DateTime.Now.AddDays(-(DateTime.Now.Day - 1)).ToString("M/d/yyyy");
            var dtStartDate = Convert.ToDateTime(strStartDate);

            var strEndDate = DateTime.Now.AddDays(1).ToString("M/d/yyyy");
            var dtEndDate = Convert.ToDateTime(strEndDate);

            var orders = db.Orders.Where(o =&gt; o.DateCompleted &gt;= dtStartDate
                                        &amp;&amp; o.DateCompleted &lt; dtEndDate
                                        &amp;&amp; (o.Status == 1 || o.Status == 2)
                                        &amp;&amp; o.Kiosk != 0).AsEnumerable();

            var total = (from o in orders
                         where o.SalesRepID == user.SalesRepID
                         select o.OrderTotal).Sum();

            TeamSales TeamSales = new TeamSales();

            TeamSales.userId = user.userID;
            TeamSales.TotalSales = total;


            lstTeamSales.Add(TeamSales);

            }

        }

        int rank = lstTeamSales.OrderByDescending(x =&gt; x.TotalSales).FindIndex(x =&gt; x.userId == CurrentUserId);

        if (rank == -1)
        {
            currentUserRank = 0;
        }
        else
        {
            // Zero based index need to add one to rank
            currentUserRank = rank + 1;
        }

    }

    return currentUserRank;
}


I have .FindIndex added as an extension method to IEnumerable.

All I really need is to get the rank of the person logged in in comparison to everyone else sales.
Try what's below on for size. The date calculation is moved out of the loop, the TeamSales list capacity is pre-allocated and finally, the two LINQ statements are combined into one and rolled into AddRange rather than the explicit loop.

public static int GetNationalRank(int teamId, int CurrentUserId)
{
    int currentUserRank;
    var startDate = Convert.ToDateTime(DateTime.Now.AddDays(-(DateTime.Now.Day - 1)).ToString("M/d/yyyy"));
    var endDate = Convert.ToDateTime(DateTime.Now.AddDays(1).ToString("M/d/yyyy"));
    List&lt;ProPit_User&gt; proPitUsers;

    using (var ppdb = new ProsPitEntities())
    {
        proPitUsers = ppdb.ProPit_User.Where(x =&gt; x.SalesRepID != null).ToList();
    }

    var teamSales = new List&lt;TeamSales&gt;(proPitUsers.Count());

    using (var db = new TraegerEntities())
    {
        teamSales.AddRange(proPitUsers
            .Select(user =&gt; new
            {
                user,
                total = db.Orders.Where(o =&gt; o.DateCompleted &gt;= startDate
                    &amp;&amp; o.DateCompleted &lt; endDate
                    &amp;&amp; (o.Status == 1 || o.Status == 2)
                    &amp;&amp; o.Kiosk != 0
                    &amp;&amp; o.SalesRepID == user.SalesRepID).Select(o =&gt; (decimal?)o.OrderTotal).Sum() ?? 00.0M
            })
            .Select(userTotal =&gt; new TeamSales { userId = userTotal.user.userID, TotalSales = userTotal.total }));

        var rank = teamSales
            .OrderByDescending(x =&gt; x.TotalSales)
            .FindIndex(x =&gt; x.userId == CurrentUserId);

        currentUserRank = rank == -1 ? 0 : rank + 1;
    }

    return currentUserRank;
}