Лучший способ периодически удалять набор записей с LINQ to SQL - PullRequest
2 голосов
/ 19 ноября 2008

Это мой первый взлом метода, который периодически запускается в течение срока службы моего приложения ASP.NET для очистки истекших сеансов, хранящихся в моей базе данных. Кажется, это работает довольно хорошо, но разработчик программного обеспечения во мне не чувствует себя "правильно" по поводу этого кода. Я работаю с LINQ to SQL уже несколько месяцев, но я не очень уверен в следующем коде. Я беспокоюсь о нескольких вещах:

  1. Безопасен ли следующий код для выполнения в ситуации, когда к моей базе данных обращаются разные потоки? Я достаточно хорошо понимаю идею транзакций, но хочу убедиться, что я правильно их использую.

  2. Мой запрос вызовет проблемы с производительностью? Или в этом случае уместно выбрать все записи в этой конкретной таблице? Этот метод выполняется только каждые 15 минут, поэтому запрос не будет выполняться снова и снова за короткий промежуток времени.

  3. Есть ли лучший способ, которым я мог бы сделать это? У меня есть ноющее чувство, что есть.

Код:

/// <summary>
/// Method, run periodically, to remove all sign in records that correspond to expired sessions.
/// </summary>
/// <param name="connectionString">Database connection string</param>
/// <returns>Number of expired sign in records removed</returns>
public static int Clean(String connectionString)
{
    MyDatabaseDataContext db = new MyDatabaseDataContext(connectionString);

    var signIns = db.SignIns.Select(x => x);
    int removeCount = 0;

    using (TransactionScope scope = new TransactionScope())
    {
        foreach (SignIn signIn in signIns)
        {
            DateTime currentTime = DateTime.Now;
            TimeSpan span = currentTime.Subtract(signIn.LastActivityTime);

            if (span.Minutes > 10)
            {
                db.SignIns.DeleteOnSubmit(signIn);
                ++removeCount;
            }
        }

        db.SubmitChanges();
        scope.Complete();
    }

    return removeCount;
}

Ответы [ 4 ]

7 голосов
/ 19 ноября 2008

Это звучит как то, что вы могли бы легко сделать в sproc. SQLServer предоставляет метод GETDATE (), который возвращает текущее время ... Я не понимаю, почему вы не можете просто

 DELETE * FROM tblSignIns 
 WHERE LastActivityTime < DATEADD("minute", -10, GETDATE());

Разве это не делает то же самое?

2 голосов
/ 19 ноября 2008

Один комментарий: вы не хотите TimeSpan.Minutes, вы хотите TimeSpan.TotalMinutes. Вполне возможно, что это не имеет значения в большинстве случаев времени, но по крайней мере это логическая ошибка:)

1 голос
/ 25 ноября 2008

FWIW Недавно я опубликовал фрагмент кода, демонстрирующий реализацию основанных на наборе / пакетных обновлений для Linq (обновление одного оператора вместо записи за записью).

Я не опубликовал версию для удаления того же самого, но скоро сделаю (читай: когда я в настроении напечатать еще одну запись в блоге :)). Между тем вы можете получить его из версии оператора «update».

Описание и исходный код вы найдете здесь: http://blog.huagati.com/res/index.php/2008/11/05/architecture-linq-to-sql-and-set-based-operations-update-statements/

Обновление: пример 'удаления' можно найти здесь: http://blog.huagati.com/res/index.php/2008/11/25/architecture-linq-to-sql-and-set-based-operations-delete-statements/

1 голос
/ 19 ноября 2008

Вы можете сохранить сохраненный процесс в качестве метода в контексте вашей базы данных. Почему бы не написать тот, который делает то, что вы хотите, а затем назвать его через свой контекст? Таким образом, вы также можете использовать логику множеств, а не перебирать свою коллекцию. (Linq to SQL может скомпилировать это - не уверен, как он справляется с удалением.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...