私はこのクエリを持っていると私はこの関数でエラーが出ます:
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
これは、別のクエリの結果を繰り返し処理しながらクエリを実行した場合に発生する可能性があります。例が完全ではないので、これがどこで起こるかはあなたの例からはっきりしません。
これを引き起こす可能性がある1つのことは、あるクエリの結果を反復処理するときに引き起こされる遅延ロードです。
これは、接続文字列でMARSを許可することで簡単に解決できます。接続文字列のプロバイダ部分(データソース、初期カタログなどが指定されている場所)にMultipleActiveResultSets=true
を追加します。
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;
}
再度読み直されないように、構文.ToList()
を使用して、dbから読み込まれたオブジェクトをリストに変換します。これがうまくいくことを願っています。ありがとう。
参照が必要な人のための実用的な接続文字列です。
<connectionStrings>
<add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>
私の場合、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);
}
}
}
}
これが重複回答かどうかはわかりません。それであれば申し訳ありません。 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
}
同じ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で列挙を強制することができます。
に加えて - 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から読み取る読み取り専用プロパティでもあります。
読み取りループ内でいくつかのレコードを更新しようとしたときに同じエラーが発生しました。私は最も投票された答えMultipleActiveResultSets=true
を試してみました、そしてそれが次のエラーを得るためのただの回避策であることがわかりました
セッション内で他のスレッドが実行中のため、新しいトランザクションは許可されません
巨大なResultSetに有効な最善のアプローチは、 Entity FrameworkからのSqlException - セッション内で実行されているスレッドが他にあるため、新しいトランザクションは許可されない で説明されているようにチャンクごとに別々のコンテキストを開くことです
Googleでこれを見つけた人のために。
このエラーが発生したのは、エラーで示唆されているように、同じSqlCommandで別のSqlDataReaderを作成する前にSqlDataReaderを閉じられなかったためです。
2番目のリーダーを作成する前にsqlDataReader.Close();
を呼び出すことで問題を解決しました。
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操作はまだ準備ができていないため.
この問題はEntity Frameworkの「遅延ロード」機能が原因で発生する可能性があります。通常、最初のフェッチ中に明示的に要求されていない限り、すべての結合データ(他のデータベーステーブルに格納されているもの)は要求されたときにのみフェッチされます。多くの場合、これは良いことです。不要なデータをフェッチすることを防ぎ、クエリのパフォーマンスを向上させ(結合しない)、帯域幅を節約するためです。
この問題で説明されている状況では、最初のフェッチが実行され、「選択」フェーズで遅延読み込みデータが欠落していることが要求され、その後EFが「open DataReader」について文句を言います。
受け入れられた答えで提案された回避策はこれらの質問の実行を可能にするでしょう、そして確かに全体の要求は成功するでしょう。
ただし、データベースに送信された要求を調べると、複数の要求、つまり欠落している(遅延ロードされた)データごとに追加の要求があることに気付くでしょう。これはパフォーマンスキラーになるかもしれません。
より良い方法は、最初の問い合わせの間に、必要なすべての遅延ロードデータをプリロードするようにEFに指示することです。これは "Include"ステートメントを使って行うことができます。
using System.Data.Entity;
query = query.Include(a => a.LazyLoadedProperty);
このようにして、必要なすべての結合が実行され、必要なすべてのデータが単一のクエリとして返されます。質問に記載されている問題は解決されます。
私は自分のツールでWebサービスを使用しています。これらのサービスはストアドプロシージャを取得します。より多くのクライアントツールがWebサービスを取得する一方で、この問題が発生します。ストアドプロシージャを取得する関数にSynchronized属性を指定することで修正しました。今それはうまく機能している、エラーは私のツールに現れなかった。
[MethodImpl(MethodImplOptions.Synchronized)]
public static List<t> MyDBFunction(string parameter1)
{
}
この属性により、一度に1つの要求を処理できます。これで問題は解決しました。
私の場合は、接続文字列でMultipleActiveResultSets
をTrue
に設定する必要がありました。
それから、同じデータコンテキストで同時に2つの(SQL)コマンドを実行できないという別のエラー(本当のエラー)が発生しました。 (EFコア、コード優先)
それで私のための解決策は私が両方のコマンドのためにただ一つのDbContextを持っていたので、他の 非同期 コマンド実行を探して 同期 に変えることでした。
お役に立てば幸いです。
私にとってはそれは私自身のバグでした。 SqlCommand.executeReader()
を使うべきだったのに、SqlCommand.ExecuteNonQuery()
を使ってINSERT
を実行しようとしていました。開かれて閉じられなかったため、エラーが発生しました。この見落としに注意してください。
ちなみに...これはSQLオブジェクトからの(内部の)データマッピングに問題があるときにも起こります。
例えば...
偶然 がVARCHAR
...を返したSQL Scalar Function
を作成し、それを使用してVIEW
の列を生成しました。 VIEW
はDbContext
...に正しくマッピングされていたので、 Linq はそれを問題なく呼び出していました。しかし、 エンティティ expected DateTime? そしてVIEW
は String を返していました。
どの奇妙なスロー...
「最初に閉じる必要がある、このCommandに関連付けられている開いているDataReaderが既にあります」
理解するのは難しかったですが...戻り値のパラメータを修正した後は...すべて順調でした
これは実社会のシナリオから抜粋したものです。
結論として、MultipleActiveResultSetsを忘れずに、非常にコストがかかる可能性がある冗長なdb呼び出しを見つける前にコードが実行された可能性があります。MultipleActiveResultSets属性の設定だけでなくout)失敗した場所でコードがそれを必要とする理由。