Неправильная попытка вызова Read, когда читатель закрыт

У меня есть несколько частей кода в разных классах, которые используют этот или очень похожий код для извлечения некоторых данных из базы данных SQL Server. Большинство из них работают, но я сталкиваюсь с проблемой некоторых и действительно не понимаю, почему. Приведенный выше код будет выполняться в течение 60-64 раз, извлекая строки, но затем прекратит работу с ошибкой чтения. Я отследил записи для чего угодно, но, похоже, просто попал в любую точку между этими записями и остановками. Нет никаких вызовов из этого класса в какие-либо другие функции класса, по сути, это запущенная вещь.

У моей строки подключения есть время вне 600 секунд, и у меня также установлен mars. другое примечание; это вызывается из Parallel.ForEach с параллелизмом, установленным в 2.

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

когда я избавляюсь от Parallel.ForEach и просто запускаю его как foreach, он работает. Мне нужны эти темы, или это займет слишком много времени. И мне также любопытно, где читатель закрывается.

Исключение: System.InvalidOperationException- Недопустимая попытка вызвать Read, когда читатель закрыт.

Вызывается код:

 public string GetUnderwritingType(string id)
    {
        UnderwritingType uwt = new UnderwritingType();
        GetRequiredPercent(id, ref uwt);
        GetParticipation(id, ref uwt);
        return CalculateUnderwritingType(ref uwt);
    }
    private void GetRequiredPercent(string id, ref UnderwritingType uwt)
    {
        DataCommon common = new DataCommon(Settings.Default.ReqPercentSP, id);
        try
        {
      /******* Error on this reader statement ********/      
using (SqlDataReader reader = common.Command.ExecuteReader(CommandBehavior.CloseConnection))               {
                /* no data */
                if (reader.HasRows == false) return;
                while (reader.Read())
                {
                    uwt.RequiredPercent.Add(Double.Parse(reader[REQ_PERCENT_FIELD].ToString()));
                    uwt.MinimumCount.Add(Int32.Parse(reader[MIN_COUNT_FIELD].ToString()));
                    uwt.UWType.Add(Int32.Parse(reader[UW_LEVEL_FIELD].ToString()));
                }
            }
        }
        catch (InvalidOperationException)
        {
            if (common.Connection.State == ConnectionState.Open) common.Connection.Close();
            throw;
        }
        catch (SqlException)
        {
            if (common.Connection.State == ConnectionState.Open) common.Connection.Close();
            throw;
        }
    }  

Код, который устанавливает соединение:

   public class DataCommon
    {
        private readonly SqlCommand _command;
        private SqlConnection _connection;

        public DataCommon(string storedProcedure, string id)
        {
            SetConnection();
            _command = new SqlCommand(storedProcedure, Connection);
            if (_command != null) _command.CommandType = CommandType.StoredProcedure;
            _command.Parameters.Add("@Id", SqlDbType.NVarChar).Value = id;
        }
        /// <summary>
        ///   Gets the database connection.
        /// </summary>
        public SqlConnection Connection
        {
            get { return _connection; }
        }
        /// <summary>
        ///   Gets the database command object.
        /// </summary>
        public SqlCommand Command
        {
            get { return _command; }
        }
        /// <summary>
        ///   Sets the database connection.
        /// </summary>
        private void SetConnection()
        {
            _connection = new SqlConnection {ConnectionString = Settings.Default.TestConnection};
            _connection.Open();
            if (_connection.State != ConnectionState.Open)
                throw new DataException(Settings.Default.ConnectionErrorMessage);
        }
    }

Строка подключения: источник данных =xxxxx; исходный каталог = ггггг;Trusted_Connection=True;MultipleActiveResultSets=True; время ожидания подключения =600;

Трассировка стека:\ GroupData \ EligibilityClassData.cs: строка 95 в GroupLogic.GroupExtract.BuildEligibilityClass(идентификатор строки, группа и группа) в C:\Subversion\branch \Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs: строка 188 в GroupLogxt. > c_DisplayClass2.b_1 () в C:\Subversion\branch \Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs: строка 113 в System.Threading.Tasks.Task.InnerInvoke() в System.Threading.Tasks.Task.Execute()

Первоначальный вызов для прохождения цикла (при преобразовании в обычный foreach, все в порядке):

ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2;
Parallel.ForEach(ids, options, id => BuildGroup(id));

звонки

private void BuildGroup(string id)
{
   Group[] group = { new Group() };
    Task eligibilityBlock = Task.Factory.StartNew(() =>
                                            BuildEligibilityClass(id, ref @group[0]));
            Task.WaitAny(eligibilityBlock);
             GroupList.Add(@group[0]);
}

Какие звонки

    private static void BuildEligibilityClass(string id, ref Group group)
    {
        EligibilityClassData eligClassData = new EligibilityClassData();
        group.EligibilityClassList = eligClassData.GetEligibilityClass(id);

    }

который попадает в одну из тех читает.

2 ответа

Можете ли вы увеличить значения времени ожидания в следующих двух местах и ​​попробовать?

  1. Тайм-аут MSDTC в службах компонентов.
  2. System.Transaction в machine.config сервера приложений.

Ссылка:

  1. Ошибка "Неправильная попытка вызова Read, когда читатель закрыт" (только для длительных операций)

Я с ником на этом... "CommandBehavior.CloseConnection" закроет ваше соединение на первом завершающемся потоке (который объясняет несоответствие). Попробуйте удалить это и удалить Закрытие соединений в "catch" (только для тестирования).

Другие вопросы по тегам