Как эффективно обновлять огромное количество данных с помощью кода

#c# #asp.net #sql-server #linq

#c# #asp.net #sql-сервер #linq

Вопрос:

Я работаю над обновлением огромного количества данных. Около 200 тыс. данных в конкретной таблице. Но я нахожу свой код неэффективным и медленным. Есть ли способ оптимизировать этот код и сделать его в два или три раза быстрее? Я пытаюсь преобразовать их существующий пароль в хэшированный. Я пробовал linq раньше, но столкнулся с проблемой «Тайм-аута выполнения». До сих пор я не могу найти решение этой проблемы. Приведенный ниже код был тем, который я использую в настоящее время.

 var hashedProvider = Membership.Providers["HashedProvider"];
if (hashedProvider != null)
{
    using (SqlConnection con = new SqlConnection(System.Configuration
        .ConfigurationManager.ConnectionStrings["Connection"].ConnectionString))
    {
        con.Open();
        string sql = "SELECT Email from aspnet_membership where IsLockedOut = '0'"  
            " AND IsApproved = '1' And PasswordFormat != '1'";
        SqlCommand cmd = new SqlCommand(sql, con);
        SqlDataReader Reader = cmd.ExecuteReader();
        while (Reader.Read())
        {
            var UserName = Reader["Email"].ToString();
            MembershipUser user = Membership.GetUser(UserName);
            if (user != null)
            {
                Guid userID = new Guid(user.ProviderUserKey.ToString());
                string CurrentPassword = user.GetPassword();
                try
                {
                    UpdateUser(userID, 1);
                    var resetPassword = hashedProvider.ResetPassword(UserName, null);
                    bool Password_Changed = hashedProvider.ChangePassword(
                        UserName, resetPassword, CurrentPassword);
                    if (!Password_Changed)
                    {
                        UpdateUser(userID, 2);
                    }
                }
                catch (Exception e)
                {
                    UpdateUser(userID, 2);
                }
            }
        }
        if (Reader != null)
            Reader.Close();
    }
}
 

Ниже приведен код для UpdateUser() метода.

 public static void UpdateUser(Guid userID, int type)
{
    for (Int32 attempt = 1; ;)
    {
        using (SqlConnection con = new SqlConnection(System.Configuration
            .ConfigurationManager.ConnectionStrings["Connection"].ConnectionString))
        {
            con.Open();
            string Sql = "UPDATE [aspnet_Membership] SET [PasswordFormat] = @Type where"  
                " UserID = @UserID";
            SqlCommand cmd = new SqlCommand(Sql, con);
            cmd.Parameters.AddWithValue("@UserID", userID);
            cmd.Parameters.AddWithValue("@Type", type);
            cmd.ExecuteNonQuery();
            break;
        }
    }
}
 

Комментарии:

1. Я думаю, вам нужно измерить этот код, чтобы понять, где находится загрузчик. Затем мы можем начать вносить изменения и сравнивать результаты

2. Насколько медленно это происходит в настоящее время? Если вы собираетесь выполнить всю эту процедуру один раз для всех существующих пользователей и автоматически хэшировать пароли для всех будущих пользователей, стоит ли вообще оптимизировать? Он работает достаточно быстро для однопользовательского обновления, верно? Вместо того, чтобы обновлять пользователей одного за другим, вы можете массово прочитать их всех или несколько тысяч, обновить их пароль в цикле, удалить ограничения в таблице, если таковые имеются, удалить строки пользователей, которые вы подготовили для вставки, и, наконец, массово вставить строки пользователей собновленный пароль возвращается в таблицу.

3. Кроме того, этот пустой блок перехвата исключений в UpdateUser очень опасен. Если там есть ошибка, вы можете запустить бесконечный цикл, даже не зная, что произошло. Удалите его и давайте посмотрим, есть ли там проблемы.

4. Спасибо за быстрый ответ @Steve. О блоке catch. Там был код, но я его не добавлял, так как считаю, что это было неважно в этом сценарии. Прошу прощения за путаницу, сэр.

5. Использование табличного параметра (TVP) в качестве входных данных для вашей хранимой процедуры позволит вам повысить скорость в 2-3 раза. Используйте структурированный тип sql в вашем коде C #, затем используйте перечислитель. Код будет перемещать блоки вставок / обновлений одновременно.