0

我在不同的类中有几部分代码,它们使用这个或非常相似的代码从 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;初始目录=yyyyy;Trusted_Connection=True;MultipleActiveResultSets=True;连接超时=600;

堆栈跟踪: .Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) at System.Data.SqlClient.SqlDataReader.Read() at GroupDataAccess.EligibilityClassData.GetEligibilityClass(String id) in C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed \GroupData\EligibilityClassData.cs:C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs:GroupLogic.GroupExtract.BuildEligibilityClass(String id, Group& group) 的第 95 行:GroupLogic.GroupExtract 的第 188 行。< >c_ DisplayClass2.b _1() 在 C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs: System.Threading.Tasks.Task.InnerInvoke() 在 System.Threading.Tasks.Task 的第 113 行。执行()

初始调用通过循环(当转换为正常的 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);

    }

命中其中一个读数。

4

2 回答 2

0

您可以在以下两个位置增加超时值并尝试吗?

  1. 组件服务中的 MSDTC 超时。
  2. 应用服务器的 machine.config 中的 System.Transactions。

参考:

  1. “阅读器关闭时调用读取无效”错误(仅适用于长时间操作)
于 2012-11-06T05:34:41.213 回答
-1

我同意这个...“CommandBehavior.CloseConnection”将在第一个完成的线程上关闭您的连接(这解释了不一致)。尝试删除此并删除关闭“catch”中的连接(仅用于测试)。

于 2012-10-29T15:58:17.380 回答