DbContextのCommandTimeoutを設定する方法を探しています。検索した後、DbContextをObjectContextにキャストし、objectContextのCommandTimeoutプロパティの値を設定することで方法を見つけました。
var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;
しかし、私はDbContextを使用する必要があります。
DbContextのCommandTimeoutを設定する方法を探しています。検索した後、DbContextをObjectContextにキャストし、objectContextのCommandTimeoutプロパティの値を設定することで方法を見つけました。
var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;
しかし、私はDbContextを使用する必要があります。
それはあなたの方法で動作します。
またはそれをサブクラス化します(msdnフォーラムから)
public class YourContext : DbContext
{
public YourContext()
: base("YourConnectionString")
{
// Get the ObjectContext related to this DbContext
var objectContext = (this as IObjectContextAdapter).ObjectContext;
// Sets the command timeout for all the commands
objectContext.CommandTimeout = 120;
}
}
var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;
これはあなたを助けるかもしれません。
public class MyContext : DbContext
{
public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
{
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
}
}
EDMXファイルを使用するときにこの問題を解決した方法は次のとおりです。このソリューションでは、デフォルトの T4 テンプレートを変更して、生成されたクラスがカスタム DbContext クラスから継承されるようにします。これにより、デフォルトのコマンド タイムアウトと、それを変更するプロパティが指定されます。
Visual Studio 2012 と EF 5.0 を使用しています。あなたの経験は、他のバージョンとは異なる場合があります。
public class CustomDbContext : DbContext
{
ObjectContext _objectContext;
public CustomDbContext( string nameOrConnectionString )
: base( nameOrConnectionString )
{
var adapter = (( IObjectContextAdapter) this);
_objectContext = adapter.ObjectContext;
if ( _objectContext == null )
{
throw new Exception( "ObjectContext is null." );
}
_objectContext.CommandTimeout = Settings.Default.DefaultCommandTimeoutSeconds;
}
public int? CommandTimeout
{
get
{
return _objectContext.CommandTimeout;
}
set
{
_objectContext.CommandTimeout = value;
}
}
}
これにはオプションの機能があります。デフォルトのコマンド タイムアウトをハードコーディングしていません。代わりに、プロジェクト設定からロードして、構成ファイルの値を変更できるようにします。プロジェクト設定をセットアップして使用する方法は、この回答の範囲外です。
また、接続文字列または接続文字列名をハードコーディングしていません。生成されたコンテキスト クラスによって既にコンストラクターに渡されているため、ここでハードコードしても意味がありません。これは新しいことではありません。EDMX ファイルは既に次のコンストラクターを生成しているため、値を渡すだけです。
public MyEntities()
: base("name=MyEntities")
{
}
(これにより、構成ファイルから "MyEntities" という名前の接続文字列を読み込むように EF に指示されます)。
ObjectContext
がnullの場合、カスタム例外をスローしています。そうなることはないと思いますが、NullReferenceException
.
をフィールドに保存してObjectContext
、デフォルトをオーバーライドするためにアクセスするプロパティを作成できるようにします。
ソリューション エクスプローラーで、T4 テンプレートが表示されるように EDMX ファイルを展開します。拡張子は .tt です。
「MyModel.Context.tt」ファイルをダブルクリックして開きます。57 行目あたりで、次のように表示されます。
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
このテンプレート行は、DbContext を継承する "MyEntities" クラスのクラス定義を生成します。
代わりに、生成されたクラスが CustomDbContext を継承するように行を変更します。
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext
このファイルを保存するとすぐに、クラスが再生成されます。そうでない場合は、EDMX ファイルを右クリックして [カスタム ツールの実行] を選択します。EDMX ファイルの下にある "MyModel.Context.tt" ファイルを展開すると、"MyModel.Context.cs" が表示されます。それが生成されたファイルです。それを開くと、それが継承されていることがわかるはずですCustomDbContext
。
public partial class MyEntities : CustomDbContext
それだけです。
コンテキスト クラスを からDbContext
に変更CustomDbContext
すると、「Entity Framework を使用した読み取り/書き込みアクションとビューを備えたコントローラー」テンプレートを使用して新しい MVC コントローラー クラスを追加しようとすると、Visual Studio でエラーが発生します。「サポートされていないコンテキスト タイプです。」と表示されます。これを回避するには、生成された "MyModel.Context.cs" クラスを開き、継承する型を一時的に に戻しDbContext
ます。新しいコントローラーを追加したら、元に戻すことができますCustomDbContext
。
それが役立つ場合、これは VB.Net ソリューションです。
Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout
このようなグローバル設定ではなく、単一のコマンドのタイムアウトを設定する例を探してここに来ました。
私がこれをどのように達成したかの例を誰かが持っていると、おそらく誰かに役立つと思います:
var sqlCmd = new SqlCommand(sql, context.Database.Connection as SqlConnection);
sqlCmd.Parameters.Add(idParam);
sqlCmd.CommandTimeout = 90;
if (sqlCmd.Connection.State == System.Data.ConnectionState.Closed)
{
sqlCmd.Connection.Open();
}
sqlCmd.ExecuteNonQuery();
sqlCmd.Connection.Close();
@PerryTriboletの答えはEF6には良さそうですが、EF5でも機能します。EF の場合、これを行う 1 つの方法があります。ObjectContext を作成し、それに CommandTimeout を設定してから、ObjectContext から DBContext を作成します。両方のオブジェクトを一緒に破棄するようにフラグを設定しました。VB.NET での例を次に示します。
Dim context As New ObjectContext("name=Our_Entities")
Dim dbcontext As New System.Data.Entity.DbContext(context, True)
With context
.CommandTimeout = 300 'DBCommandTimeout
End With
もちろん、「With」を使用する必要はありません。