0

このコードまたは非常によく似たコードを使用して、SQL Server データベースからデータを取得するさまざまなクラスのコードがいくつかあります。それらのほとんどは機能しますが、いくつかの問題が発生しており、その理由が本当にわかりません。上記のコードは 60 ~ 64 回実行され、行を取得しますが、無効な読み取りエラーが発生して終了します。あらゆるヒントについて記録をたどりましたが、それらの記録と停止の間のどこかにヒットしたようです。このクラスから他のクラス関数への呼び出しはありません。本質的に、これは実行されている唯一のものです。

私の接続文字列には 600 秒のタイムアウトがあり、mars も設定されています。別のメモ; これは、並列度が 2 に設定された Parallel.ForEach から呼び出されています。

私が言ったように、私はこのコードの構造をプログラム全体の複数の場所で使用していますが、そのほとんどはうまく機能しています。私が心配しているのは、エラーだけではなく、その発生の不一致です。

Parallel.ForEach を取り除き、foreach として実行すると、機能します。私はそれらのスレッドが必要ですが、そうしないと時間がかかりすぎます。そして、読者がどこで締めくくっているのかも気になります。

Exception : 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);
        }
    }

接続文字列: Data Source=xxxxx;Initial Catalog=yyyyy;Trusted_Connection=True;MultipleActiveResultSets=True;Connection Timeout=600;

スタック トレース: C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed の GroupDataAccess.EligibilityClassData.GetEligibilityClass(String id) の System.Data.SqlClient.SqlDataReader.Read() での .Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) \GroupData\EligibilityClassData.cs: C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs の GroupLogic.GroupExtract.BuildEligibilityClass(String id, Group& group) の 95 行目: GroupLogic.GroupExtract の 188 行目。C:\Subversion\branches\Fimmas\FimmasToInfoHub\GroupHubFeed\GroupLogic\GroupExtract.cs: System.Threading.Tasks.Task.InnerInvoke() の 113 行目 System.Threading.Tasks.Task のc_ DisplayClass2.b _1() 。実行する()

ループを通過する最初の呼び出し(通常の 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);

    }

それらの読み取りの1つにヒットします。

4

2 に答える 2

0

次の 2 か所でタイムアウト値を増やして試してみることはできますか?

  1. コンポーネント サービスでの MSDTC タイムアウト。
  2. アプリケーション サーバーの machine.config の System.Transactions。

参照:

  1. 「リーダーが閉じているときに Read を呼び出す無効な試行です」エラー (時間のかかる操作のみ)
于 2012-11-06T05:34:41.213 に答える
-1

私はこれについてニックネームを持っています...「CommandBehavior.CloseConnection」は、終了した最初のスレッドで接続を閉じます(これが矛盾を説明しています)。これを削除して、「キャッチ」内の接続を削除してください(テストのためだけに)。

于 2012-10-29T15:58:17.380 に答える