При изменении текста команды linq-to-sql соединение должно быть закрыто? - PullRequest
1 голос
/ 28 января 2011

Я изменяю командный текст linq-to-sql, чтобы заставить его использовать nolock, вот так ...

if (db.Connection.State == System.Data.ConnectionState.Closed)
    db.Connection.Open();

var cmd = db.GetCommand(db.Customers.Where(p => p.ID == 1));

cmd.CommandText = cmd.CommandText.Replace("[Customers] AS [t0]", "[Customers] AS [t0] WITH (NOLOCK)");

var results = db.Translate(cmd.ExecuteReader());

Это приложение MVC, поэтому текст данных находится в базовом контроллере и, возможно, использовался до этого кода и, что более важно, после. Должен ли я закрывать соединение в этой процедуре? Или нет вообще? Или только если я открою его здесь?


Обновление:

Сейчас я использую более общую функцию (в классе DataContext), чтобы изменить командный текст и закрыть соединение, если оно было открыто здесь. И открытие было перемещено вниз в ExecuteReader. До сих пор это работало и уменьшало спорадические проблемы тупиковой ситуации. Результаты не должны быть с точностью до секунды.

    public List<T> GetWithNolock<T>(IQueryable<T> query)
    {
        // to skip nolock, just...
        // return query.ToList();

        List<T> results = null;

        bool opened = false;

        try
        {
            if (Connection.State == System.Data.ConnectionState.Closed)
            {
                Connection.Open();

                opened = true;
            }

            using (var cmd = GetCommand(query))
            {
                cmd.CommandText = Regex.Replace(cmd.CommandText, @"((from|inner join) \[dbo.*as \[t\d+\])", "$1 with (nolock)", RegexOptions.IgnoreCase);

                results = Translate<T>(cmd.ExecuteReader()).ToList();
            }
        }
        finally
        {
            if (opened && Connection.State == System.Data.ConnectionState.Open)
            {
                Connection.Close();
            }
        }

        return results;
    }

В прошлом я обнаружил, что использование транзакции рекомендованным способом приводит к тому, что на сайте кончаются соединения в одночасье. Насколько я знаю, это ошибка в linq-to-sql. Могут быть способы обойти это, но я пытаюсь сохранить мой основной код простым. Я теперь "просто" должен сделать это ...

var users = GetWithNolock<User>(
  Users
  .Where(u => my query
);

1 Ответ

0 голосов
/ 28 января 2011

Если вы откроете его, вы должны закрыть его. Другие операции LinqToSql соответствуют этому шаблону.

В моем коде я безоговорочно открываю соединение и окончательно закрываю соединение Если кто-то передает мне открытое соединение, это их вина, и я закрываю его для них.

Вы можете отложить открытие соединения до выполнения ExecuteReader.

...