web-dev-qa-db-ja.com

このコマンドに関連付けられたオープンDataReaderが既に存在しており、最初にクローズする必要があります。

私はこのクエリを持っていると私はこの関数でエラーが出ます:

var accounts = from account in context.Accounts
               from guranteer in account.Gurantors
               select new AccountsReport
               {
                   CreditRegistryId = account.CreditRegistryId,
                   AccountNumber = account.AccountNo,
                   DateOpened = account.DateOpened,
               };

 return accounts.AsEnumerable()
                .Select((account, index) => new AccountsReport()
                    {
                        RecordNumber = FormattedRowNumber(account, index + 1),
                        CreditRegistryId = account.CreditRegistryId,
                        DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
                        AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
                    })
                .OrderBy(c=>c.FormattedRecordNumber)
                .ThenByDescending(c => c.StateChangeDate);


public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
    return (from h in context.AccountHistory
            where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
            select h.LastUpdated).Max();
}

エラーは

最初に閉じる必要があるこのCommandに関連付けられている開いているDataReaderが既にあります。

更新:

追加されたスタックトレース:

InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.]
   System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) +5008639
   System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) +23
   System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) +144
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +87
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
   System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
   System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +443

[EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.]
   System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +479
   System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +683
   System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +119
   System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +38
   System.Linq.Enumerable.Single(IEnumerable`1 source) +114
   System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3(IEnumerable`1 sequence) +4
   System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable`1 query, Expression queryRoot) +29
   System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) +91
   System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(Expression expression) +69
   System.Linq.Queryable.Max(IQueryable`1 source) +216
   CreditRegistry.Repositories.CreditRegistryRepository.DateLastUpdated(Int64 creditorRegistryId, String accountNo) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1497
   CreditRegistry.Repositories.CreditRegistryRepository.<AccountDetails>b__88(AccountsReport account, Int32 index) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1250
   System.Linq.<SelectIterator>d__7`2.MoveNext() +198
   System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
   System.Linq.<GetEnumerator>d__0.MoveNext() +96
544
DotnetSparrow

これは、別のクエリの結果を繰り返し処理しながらクエリを実行した場合に発生する可能性があります。例が完全ではないので、これがどこで起こるかはあなたの例からはっきりしません。

これを引き起こす可能性がある1つのことは、あるクエリの結果を反復処理するときに引き起こされる遅延ロードです。

これは、接続文字列でMARSを許可することで簡単に解決できます。接続文字列のプロバイダ部分(データソース、初期カタログなどが指定されている場所)にMultipleActiveResultSets=trueを追加します。

1131
Ladislav Mrnka

returnステートメントの前にToList()メソッドを使用できます。

var accounts =
from account in context.Accounts
from guranteer in account.Gurantors

 select new AccountsReport
{
    CreditRegistryId = account.CreditRegistryId,
    AccountNumber = account.AccountNo,
    DateOpened = account.DateOpened,
};

 return accounts.AsEnumerable()
               .Select((account, index) => new AccountsReport()
                       {
                           RecordNumber = FormattedRowNumber(account, index + 1),
                           CreditRegistryId = account.CreditRegistryId,
                              DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
                           AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)}).OrderBy(c=>c.FormattedRecordNumber).ThenByDescending(c => c.StateChangeDate).ToList();


 public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
    {
        var dateReported = (from h in context.AccountHistory
                            where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
                            select h.LastUpdated).Max();
        return dateReported;
    }
192
kazem

再度読み直されないように、構文.ToList()を使用して、dbから読み込まれたオブジェクトをリストに変換します。これがうまくいくことを願っています。ありがとう。

20
Icemark Muturi

参照が必要な人のための実用的な接続文字列です。

  <connectionStrings>
    <add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
  </connectionStrings>
18
Yang Zhang

私の場合、Include()を使用するとこのエラーが解決され、状況によっては結合を使用して一度にすべてのクエリを実行できる場合は複数のクエリを発行するよりもはるかに効率的になります。

IEnumerable<User> users = db.Users.Include("Projects.Tasks.Messages");

foreach (User user in users)
{
    Console.WriteLine(user.Name);
    foreach (Project project in user.Projects)
    {
        Console.WriteLine("\t"+project.Name);
        foreach (Task task in project.Tasks)
        {
            Console.WriteLine("\t\t" + task.Subject);
            foreach (Message message in task.Messages)
            {
                Console.WriteLine("\t\t\t" + message.Text);
            }
        }
    }
}
16
Despertar

これが重複回答かどうかはわかりません。それであれば申し訳ありません。 ToList()を使用して自分の問題を解決した方法を必要な人に知らせたいだけです。

私の場合は、以下のクエリでも同じ例外が発生しました。

int id = adjustmentContext.InformationRequestOrderLinks.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).Max(item => item.Id);

私は以下のように解決しました

List<Entities.InformationRequestOrderLink> links = adjustmentContext.InformationRequestOrderLinks
.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).ToList();

int id = 0;

if (links.Any())
{
  id = links.Max(x => x.Id);
 }
if (id == 0)
{
//do something here
}
7
Ziggler

同じEFコンテキストを使用してアクティブなクエリ内からDateLastUpdatedを呼び出すと、DateLastUpdateはデータストア自体にコマンドを発行します。 Entity Frameworkは、一度にコンテキストごとにアクティブなコマンドを1つだけサポートします。

上記の2つのクエリを次のように1つにリファクタリングできます。

return accounts.AsEnumerable()
        .Select((account, index) => new AccountsReport()
        {
          RecordNumber = FormattedRowNumber(account, index + 1),
          CreditRegistryId = account.CreditRegistryId,
          DateLastUpdated = (
                                                from h in context.AccountHistory 
                                                where h.CreditorRegistryId == creditorRegistryId 
                              && h.AccountNo == accountNo 
                                                select h.LastUpdated).Max(),
          AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
        })
        .OrderBy(c=>c.FormattedRecordNumber)
        .ThenByDescending(c => c.StateChangeDate);

また、クエリでFormattedAccountNumberやFormattedRecordNumberなどの関数を呼び出していることにも気付きました。データベースからエンティティデータモデルにインポートして正しくマッピングしたストアドプロシージャまたは関数でない限り、これらは関数をデータストアに送信できるステートメントに変換する方法がわからないため、例外も発生します。

また、AsEnumerableを呼び出してもクエリの実行が強制されるわけではありません。列挙されるまでクエリの実行が延期されるまで。必要に応じて、ToListまたはToArrayで列挙を強制することができます。

4
James Alexander

に加えて - Ladislav Mrnka - answer:

設定 タブでコンテナを公開および上書きしている場合は、 MultipleActiveResultSet をTrueに設定できます。このオプションは、 Advanced ... をクリックすると表示され、 Advanced groupの下に表示されます。

私の場合は、データコンテキストからクエリを開きました。

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)) _

...そして、その後、同じように問い合わせました...

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)).ToList

最初の私の問題を解決するために.ToListを追加しました。これを次のようなプロパティでラップするのは理にかなっていると思います。

Public ReadOnly Property Stores As List(Of Store)
    Get
        If _stores Is Nothing Then
            _stores = DataContext.Stores _
                .Where(Function(d) Filters.Contains(d.code)).ToList
        End If
        Return _stores
    End Get
End Property

_storesはプライベート変数で、FiltersはAppSettingsから読み取る読み取り専用プロパティでもあります。

2
Adam Cox

読み取りループ内でいくつかのレコードを更新しようとしたときに同じエラーが発生しました。私は最も投票された答えMultipleActiveResultSets=trueを試してみました、そしてそれが次のエラーを得るためのただの回避策であることがわかりました

セッション内で他のスレッドが実行中のため、新しいトランザクションは許可されません

巨大なResultSetに有効な最善のアプローチは、 Entity FrameworkからのSqlException - セッション内で実行されているスレッドが他にあるため、新しいトランザクションは許可されない で説明されているようにチャンクごとに別々のコンテキストを開くことです

1

Googleでこれを見つけた人のために。
このエラーが発生したのは、エラーで示唆されているように、同じSqlCommandで別のSqlDataReaderを作成する前にSqlDataReaderを閉じられなかったためです。

2番目のリーダーを作成する前にsqlDataReader.Close();を呼び出すことで問題を解決しました。

1
timelmer

Await _accountSessionDataModel.SaveChangesAsync()を変更してこの問題を解決しました。 _accountSessionDataModel.SaveChanges()へ。私のRepositoryクラスで。

 public async Task<Session> CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        await _accountSessionDataModel.SaveChangesAsync();
     }

それをに変更しました:

 public Session CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        _accountSessionDataModel.SaveChanges();
     }

問題は、(コードで)セッションを作成した後にフロントエンドでセッションを更新したことですが、SaveChangesAsyncは非同期的に発生するため、SaveChangesAsync操作はまだ準備ができていないため.

1
woutercx

この問題はEntity Frameworkの「遅延ロード」機能が原因で発生する可能性があります。通常、最初のフェッチ中に明示的に要求されていない限り、すべての結合データ(他のデータベーステーブルに格納されているもの)は要求されたときにのみフェッチされます。多くの場合、これは良いことです。不要なデータをフェッチすることを防ぎ、クエリのパフォーマンスを向上させ(結合しない)、帯域幅を節約するためです。

この問題で説明されている状況では、最初のフェッチが実行され、「選択」フェーズで遅延読み込みデータが欠落していることが要求され、その後EFが「open DataReader」について文句を言います。

受け入れられた答えで提案された回避策はこれらの質問の実行を可能にするでしょう、そして確かに全体の要求は成功するでしょう。

ただし、データベースに送信された要求を調べると、複数の要求、つまり欠落している(遅延ロードされた)データごとに追加の要求があることに気付くでしょう。これはパフォーマンスキラーになるかもしれません。

より良い方法は、最初の問い合わせの間に、必要なすべての遅延ロードデータをプリロードするようにEFに指示することです。これは "Include"ステートメントを使って行うことができます。

using System.Data.Entity;

query = query.Include(a => a.LazyLoadedProperty);

このようにして、必要なすべての結合が実行され、必要なすべてのデータが単一のクエリとして返されます。質問に記載されている問題は解決されます。

1
Illidan

私は自分のツールでWebサービスを使用しています。これらのサービスはストアドプロシージャを取得します。より多くのクライアントツールがWebサービスを取得する一方で、この問題が発生します。ストアドプロシージャを取得する関数にSynchronized属性を指定することで修正しました。今それはうまく機能している、エラーは私のツールに現れなかった。

 [MethodImpl(MethodImplOptions.Synchronized)]
 public static List<t> MyDBFunction(string parameter1)
  {
  }

この属性により、一度に1つの要求を処理できます。これで問題は解決しました。

0

私の場合は、接続文字列でMultipleActiveResultSetsTrueに設定する必要がありました。
それから、同じデータコンテキストで同時に2つの(SQL)コマンドを実行できないという別のエラー(本当のエラー)が発生しました。 (EFコア、コード優先)
それで私のための解決策は私が両方のコマンドのためにただ一つのDbContextを持っていたので、他の 非同期 コマンド実行を探して 同期 に変えることでした。

お役に立てば幸いです。

0
Dr TJ

私にとってはそれは私自身のバグでした。 SqlCommand.executeReader()を使うべきだったのに、SqlCommand.ExecuteNonQuery()を使ってINSERTを実行しようとしていました。開かれて閉じられなかったため、エラーが発生しました。この見落としに注意してください。

0
Andrew Taylor

ちなみに...これはSQLオブジェクトからの(内部の)データマッピングに問題があるときにも起こります。

例えば...

偶然 VARCHAR...を返したSQL Scalar Functionを作成し、それを使用してVIEWの列を生成しました。 VIEWDbContext...に正しくマッピングされていたので、 Linq はそれを問題なく呼び出していました。しかし、 エンティティ expected DateTime? そしてVIEW String を返していました。

どの奇妙なスロー...

「最初に閉じる必要がある、このCommandに関連付けられている開いているDataReaderが既にあります」

理解するのは難しかったですが...戻り値のパラメータを修正した後は...すべて順調でした

0
Prisoner ZERO

これは実社会のシナリオから抜粋したものです。

  • 接続文字列にMultipleActiveResultSetsが設定されていると、ステージ環境でコードが適切に機能します。
  • MultipleActiveResultSets = trueを指定せずに実稼働環境に公開されたコード
  • 1つのページが失敗している間非常に多くのページ/呼び出しが機能します
  • 呼び出しを詳しく見ると、データベースに対して不要な呼び出しが行われているため、削除する必要があります。
  • ProductionでMultipleActiveResultSets = trueに設定し、クリーンアップしたコードを公開すると、すべてがうまく機能し、効率的に機能します。

結論として、MultipleActiveResultSetsを忘れずに、非常にコストがかかる可能性がある冗長なdb呼び出しを見つける前にコードが実行された可能性があります。MultipleActiveResultSets属性の設定だけでなくout)失敗した場所でコードがそれを必要とする理由

0
usefulBee