Entity Frameworkでデータベースタイムアウトを設定する


164

コマンドがタイムアウトし続けるため、デフォルトのコマンドタイムアウト値を変更する必要があります。

私は見つけましたmyDb.Database.Connection.ConnectionTimeoutが、それはreadonlyです。

Entity Framework 5でコマンドタイムアウトを設定するにはどうすればよいですか?


20
参考までに、EF6では、Database.CommandTimeout読み取り専用ではなくなりました
itho

2
@itsho彼は話していましたDatabase.Connection.ConnectionTimeout。とにかく、Database.CommandTimeoutあなたのクエリがタイムアウトしている場合は例外System.Data.Entity.Core.EntityCommandExecutionExceptionです(を含む例外System.Data.SqlClient.SqlException: Timeout expired.)。
David FerenczyRogožan2016年


1
CONNECTIONタイムアウトは実際には気にしないと思いますが、代わりにCOMMANDタイムアウトを調整します。
Worthy7

回答:


199

あなたの文脈でこれを試してください:

public class MyDatabase : DbContext
{
    public MyDatabase ()
        : base(ContextHelper.CreateConnection("Connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
    }
}

接続文字列でタイムアウトを定義する場合Connection Timeoutは、次の接続文字列のようにパラメータを使用します。

<connectionStrings>

<add name="AdventureWorksEntities"
connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
provider=System.Data.SqlClient;provider connection string='Data Source=localhost;
Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60;
multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />

</connectionStrings>

ソース:方法:接続文字列を定義する


1
接続文字列バージョンを使用することをお勧めします。ObjectContextこのコンストラクタでにアクセスしようとすると、PowerShell / NuGetコンソールコマンドが循環的に失敗することがあります
Kevin Gorski 2013年

130
接続タイムアウトとコマンドタイムアウト、および2つの別個のもの。接続文字列の設定である接続タイムアウトは、コマンドの実行時間(CommandTimeout)に影響を与えません。
クレイレンハート2013

3
私の問題は少し違いました。移行中にタイムアウトが発生しました。:EFは、移行の際に使用するためのセットに似た性質があるmsdn.microsoft.com/en-us/library/...
カルステン

2
使用するEFのバージョンに応じて、この回答を参照し、CommandTimeoutプロパティを指定する方法の異なるAPIについて理解してください。
ジム・アホ

1
私にとっては機能しません(接続とコマンドが私が疑うものと同じではありません)。この投稿は、stackoverflow.com
questions / 6232633 / entity

181

使用できます DbContext.Database.CommandTimeout = 180;

とてもシンプルで、キャストは必要ありません。


1
Fluent APIEFのフォームを使用する私たちにとって非常に便利です。
GoldBishop 2016年

20

私の部分的なコンテキストは次のようになります:

public partial class MyContext : DbContext
{
    public MyContext (string ConnectionString)
        : base(ConnectionString)
    {
        this.SetCommandTimeOut(300);
    }

    public void SetCommandTimeOut(int Timeout)
    {
        var objectContext = (this as IObjectContextAdapter).ObjectContext;
        objectContext.CommandTimeout = Timeout;
    }
}

私はSetCommandTimeOut公開したので、グローバルタイムアウトの代わりに、長い時間(5分以上)を必要とするルーチンのみを変更します。


9

生成されたコンストラクタコードでは、次を呼び出す必要があります OnContextCreated()

この部分クラスを追加して問題を解決しました:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}

8

私はロニーの答えを流暢な実装で拡張しましたので、あなたはそれを次のように使うことができます:

dm.Context.SetCommandTimeout(120).Database.SqlQuery...

public static class EF
{
    public static DbContext SetCommandTimeout(this DbContext db, TimeSpan? timeout)
    {
        ((IObjectContextAdapter)db).ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;

        return db;
    }

    public static DbContext SetCommandTimeout(this DbContext db, int seconds)
    {
        return db.SetCommandTimeout(TimeSpan.FromSeconds(seconds));
    } 
}

8

データベースの最初のアプローチの場合:

次のようにContextName.Context.tt T4テンプレートをオーバーライドすることで、コンストラクタに設定できます。

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        Database.CommandTimeout = 180;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}

Database.CommandTimeout = 180; 現実的な変化です。

生成される出力は次のとおりです。

public ContextName() : base("name=ContextName")
{
    Database.CommandTimeout = 180;
}

データベースモデルを変更すると、このテンプレートは残りますが、実際のクラスは更新されます。


設定ファイルを使用してテンプレートでタイムアウトを指定できる方法はありますか?
shas

1
何かが組み込まれているかどうかはわかりません(何かを見つけることができませんでした)。しかし、その代わりに180をハードコーディングするのは、使用することができますSystem.Configuration.ConfigurationManager.AppSettings["keyname"]@shasを
クリスチャンGollhardt

7

他の回答と同じですが、拡張メソッドとして:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}

この拡張メソッドを呼び出すにはどうすればよいですか?
ワンダーソンロペス

1

私はこの問題に遭遇し、アプリケーション構成ファイルを更新することで解決しました。問題の接続には、「接続タイムアウト= 60」を指定します(エンティティフレームワークバージョン5.0.0.0を使用しています)

ConnectionTimeout設定


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.