完了までに30秒以上かかる関数のインポートを使用すると、Entity Framework(EF)を使用してタイムアウトになります。私は以下を試みましたが、この問題を解決することができませんでした:
ここで提案されているように EDMXファイルを持つプロジェクトのApp.Configファイルの接続文字列にDefault Command Timeout=300000
を追加しました 。
これが私の接続文字列のようなものです:
<add
name="MyEntityConnectionString"
connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
res://*/MyEntities.msl;
provider=System.Data.SqlClient;provider connection string="
Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
MultipleActiveResultSets=True;Default Command Timeout=300000;""
providerName="System.Data.EntityClient" />
私は自分のリポジトリにCommandTimeoutを直接設定してみました。
private TrekEntities context = new TrekEntities();
public IEnumerable<TrekMatches> GetKirksFriends()
{
this.context.CommandTimeout = 180;
return this.context.GetKirksFriends();
}
タイムアウトからEFを取得するために他に何ができますか?これは非常に大きなデータセットに対してのみ起こります。小さなデータセットではすべてうまくいきます。
これは私が得ているエラーの一つです:
System.Data.EntityCommandExecutionException:コマンド定義の実行中にエラーが発生しました。詳細は内部の例外を見てください。 ---> System.Data.SqlClient.SqlException:タイムアウト期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。
わかりました - 私はこれがうまくいった、そして起こったことはばかげています。 Default Command Timeout=300000
の接続文字列とCommandTimeoutを180に設定しました。接続文字列からDefault Command Timeout
を削除すると、うまくいきました。だから答えはあなたのコンテキストオブジェクトのリポジトリのCommandTimeoutを以下のように手動で設定することです:
this.context.CommandTimeout = 180;
接続文字列でタイムアウト設定を設定しても、影響はありません。
EF接続文字列内でデフォルトのコマンドタイムアウトを指定することには既知のバグがあります。
http://bugs.mysql.com/bug.php?id=56806
接続文字列から値を削除し、それをデータコンテキストオブジェクト自体に設定します。接続文字列から競合する値を削除すると、これは機能します。
this.context.Database.SetCommandTimeout(180);
this.context.Database.CommandTimeout = 180;
((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;
this.context.CommandTimeout = 180;
DbContextを使用している場合は、次のコンストラクタを使用してコマンドタイムアウトを設定します。
public class MyContext : DbContext
{
public MyContext ()
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 1 * 60; // value in seconds
}
}
DbContext
とEF v6 +を使用している場合は、代わりに以下のものを使用できます。
this.context.Database.CommandTimeout = 180;
通常私はトランザクション内で自分の操作を処理します。私が経験したように、contextコマンドのtimeoutを設定するだけでは十分ではありませんが、トランザクションにはtimeoutパラメータを持つコンストラクタが必要です。正しく機能するように、両方のタイムアウト値を設定する必要がありました。
int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}
関数の終わりにprevtoのコマンドタイムアウトを以前の値に戻しました。
EF6を使う
これは非常に古いスレッドが実行されていることを私は知っていますが、それでもEFはこれを修正していません。自動生成されたDbContext
を使っている人は、次のコードを使って手動でタイムアウトを設定することができます。
public partial class SampleContext : DbContext
{
public SampleContext()
: base("name=SampleContext")
{
this.SetCommandTimeOut(180);
}
public void SetCommandTimeOut(int Timeout)
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
objectContext.CommandTimeout = Timeout;
}
私のようにEntity Frameworkを使用している場合は、スタートアップクラスのタイムアウトを次のように定義する必要があります。
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));
これが私が出資するものです。多分それは誰かに役立つでしょう:
だからここに行きます:
EFでLINQを使って、このようなリストに含まれている正確な要素を探してください。
await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();
idListに複数のIdが含まれるまで、すべて問題ありません。
リストに1つのIdしか含まれていない場合、「タイムアウト」の問題が発生します。この問題を解決するには、IdList内のID数をチェックするためのif条件を使用します。
例:
if (IdList.Count == 1)
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();
}
else
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();
}
説明:
Sql Profilerを使用して、Entity frameeorkによって生成されたSelectステートメントを確認してください。 …
DbContextとEF v6 +を使用している場合は、CommandTimeoutプロパティを使用できます。
this.context.Database.CommandTimeout = 180;