Search code examples
c#linqdatatableenumerate

Enumerate Linq Call takes 5 minutes


I'm having a performance issue with this Code, I'm reading from a DataBase and then I'm convrting the DataTable to List of CampaignRecipientLib and it takes minimum 5 minutes when i'm calling this method:

private static List<CampaignRecipientLib> GetGroupRcipientsToSchedule(int GroupId, int CustomerId, bool Delete = false, bool NewlyAddedCampaignGroupRecipient = false)
        {
            List<SqlParameter> param = new List<SqlParameter>();
            param.Add(new SqlParameter("@GroupID", GroupId));
            param.Add(new SqlParameter("@CustomerId", CustomerId));
            param.Add(new SqlParameter("@Delete", Delete));
            param.Add(new SqlParameter("@NewlyAddedCampaignGroupRecipient", NewlyAddedCampaignGroupRecipient));

            Stopwatch st = new Stopwatch();
            st.Start();
            var rec_names = SqlHelper.GetDataTable("[dbo].[p_GetRecipientListByGroupCode]", param, CommandType.StoredProcedure);
            st.Stop();
            return rec_names.AsEnumerable().Select(row =>
                 new CampaignRecipientLib
                 {
                     ID = row.Field<int>("cgr_RecipientId"),
                     CMPRID = 0,//row.Field<int>("cr_CampaignRecipientId"),
                     CMPRCode = codePrefix + Guid.NewGuid().ToString("N"),//row.Field<string>("cr_CampaignRecipientCode"),
                     CampaignId = 0,
                     SentCampaigns = string.IsNullOrEmpty(row.Field<string>("GroupScenarioList")) ? new List<int>() : row.Field<string>("GroupScenarioList").Split(',').Select(int.Parse).ToList(),
                     EmailTo = row.Field<string>("r_Email"),
                     Email = row.Field<string>("r_Email"),
                     FirstName = row.Field<string>("r_FirstName"),
                     LastName = row.Field<string>("r_LastName"),
                     Language = string.IsNullOrEmpty(row.Field<string>("r_LangCode")) ? null : row.Field<string>("r_LangCode"),
                     Scheduled = DateTime.Now,//row.Field<DateTime?>("cr_Scheduled").HasValue ? row.Field<DateTime?>("cr_Scheduled") : DateTime.Now,
                     IsdoubleBarrle = false,//row.Field<bool>("cr_IsDoubleBarrel"),
                     Offset = string.IsNullOrEmpty(row.Field<string>("r_Offset")) ? null : row.Field<string>("r_Offset"),
                     Toffset = row.Field<string>("r_Offset").StartsWith("-") ? -TimeSpan.Parse(row.Field<string>("r_Offset").Remove(0, 1)) : TimeSpan.Parse(row.Field<string>("r_Offset")),
                     ReadyTobeSent = false,//row.Field<bool>("cr_ReadyTobeSent"),
                     PickupReady = false,//row.Field<bool>("cr_PickupReady"),
                     DefaultLanguage = string.Empty//string.IsNullOrEmpty(row.Field<string>("cmp_LangCode")) ? null : row.Field<string>("cmp_LangCode")
                 }
                 ).ToList();
        }

The same call, in a different project is super fast, less than a second! I mean by different project is:windows service, and the current project where it takes longer time is: Asp Web Form application

Any clue or advise?

Note: the call to the DataBase takes 1.5 seconds to return a DataTable with 4000 rows, but the enumerate part is the one that takes most of the time

return rec_names.AsEnumerable().Select(row =>
                 new CampaignRecipientLib
                 { .... }).ToList();

==========================

Update:

Here is a screenshot of system A where it's slow:

system A where it's slow Is it possible that the marked line is the reason? because I'm converting the content of that column to a comma separated int value

here is a screenshot of system B where it's super fast, but I don't need to bind the GroupScenarioList column in this call

system B


Solution

  • I found the reason

    codePrefix was a property, and it calls a stored procedure every time for each row in the dataTable,

     return rec_names.AsEnumerable().Select(row =>
                     new CampaignRecipientLib
                     {
                         ID = row.Field<int>("cgr_RecipientId"),
                         CMPRID = 0,//row.Field<int>("cr_CampaignRecipientId"),
                         CMPRCode = codePrefix + Guid.NewGuid().ToString("N"),//row.Field<string>("cr_CampaignRecipientCode"),
                         CampaignId = 0,
                         ... ....
    

    I just changed it to be called once, by storing the unique value returned by "codePrefix" property in a local variable.