Entity Framework:このコマンドに関連付けられている開いているDataReaderが既にあります。このDataReaderは最初に閉じる必要があります

この質問はこちらに関連しています

私のリポジトリメソッドには次のコードがあります:

 public IEnumerable GetApplicationPositionHistories(int applicantId, int positionId)
        {
            return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o => o.applicantPosition) ;
        }

私のHTMLはこのコードを持っています:

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Position.name)
        </td>

The full exception is:

There is already an open DataReader associated with this Command which must be closed first.

It was throw in the first line of the HTML @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)

7

5 答え

クイックソリューション:

public IEnumerable GetApplicationPositionHistories(int applicantId, int positionId)
    {
        return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o => o.applicantPosition).ToList() ;
    }

LINQと deffered execution がどのように機能するのかを知りたい場合は、なぜこの問題を解決するのかをお読みください。いくつかの言葉で - あなたがToListによるクエリを "列挙"することによってselectの実行を "強制"しないと、実際にはビューが遅すぎます。これは、同じ接続を使用したい他のクエリに問題を引き起こしています。

21
追加された
この同じエラーは、派生クラスの1つに1対1の関係があったTPH継承構造を使用して、モデルベースクラスから継承する2つの同様のモデルクラスを再実装したときに発生しました。そのモデルのコントローラーに熱心な読み込みを使用します。この場合、わかりやすい読み込みがサポートされていないので、コントローラのこのプロパティの .Include(...)を削除し、 .ToList()</残った .Include(...)ステートメントの最後に問題が修正されたようです - ありがとうございます。
追加された 著者 Aaron Newton,

接続文字列に MultipleActiveResultSets = true; を追加しようとしましたか?

12
追加された
私はコンテキストを使用していました。 .Find(id)。何らかの理由でOPで述べたエラーが発生します。この設定を接続文字列に追加すると、問題が解決しました。
追加された 著者 CodeMonkey,

このエラーは、別のクエリの内部にいる間に新しいクエリが実行される場合に発生します。あなたの意見には、このようなものがあると考えてください

@Html.DisplayFor(modelItem => item.Device.Name)

あなたのデバイスモデルでは

    public string Name
    {
        get
        {
            return String.Format("{0} {1}", Brand.BrandName, Model.ModelName);
        }
    }

Device.Nameを評価するには、そのブランドとモデルをクエリする必要があるため、クエリ内でクエリになるため、 MutlipleActiveResultSets を次のようにデータベース接続文字列に追加します。

    
6
追加された

通常、ビュー内でEFオブジェクトは使用しませんが、ビューモデルのPOCOオブジェクトを作成し、ビューモデルにクエリ結果をマップします。 EFでは、リポジトリメソッドでクエリを実行しません。これは、定義時にクエリが実行されるのではなく、データにアクセスしようとするときだけです。あなたのビューでは、同じクエリを何度も使用していますが、これは正しくありません。

If you want to access the list of object returned by your repository method, use toList

1
追加された

あなたがLazyの場合の本当の問題クエリがこの実行を終了する前に、ApplicantPositionエンティティからPosition参照を読み込みます。そのシナリオで遅延実行を保持したい場合は、次のようにクエリにPosition参照を読み込むことができます:

Include(o => o.applicantPosition.Select(a => a.Position));

GetApplicationPositionHistoriesでIEnumerableを返し続けます。

もう1つの解決策は、クエリ上でToList()メソッドまたはToArrray()メソッドを呼び出すGetApplicationPositionHistoriesメソッドで実際にクエリを実行することです。

0
追加された