如何为DbContext设置CommandTimeout?

我正在寻找一种方法来为DbContext设置CommandTimeout。 search后,我find了通过将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; } } 

这可能会帮助你。

 public class MyContext : DbContext { public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true) { ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; } } 
 var ctx = new DbContext(); ctx.Database.CommandTimeout = 120; 

我发现改变.tt文件适用于我,因为稍后我不会丢失更改:

添加这一行:

 ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; 

紧跟在DbContext创build者之后,在!loader.IsLazy构造之前:

 <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext { public <#=code.Escape(container)#>() : base("name=<#=container.Name#>") { ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; <# if (!loader.IsLazyLoadingEnabled(container)) 

它应该出现在你生成的Context.cs中:

 public MyEntities() : base("name=MyEntities") { ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; } 

我喜欢扩展方法:

 public static class DbContextExtensions { public static void SetCommandTimeout(this ObjectContext dbContext, int TimeOut) { dbContext.CommandTimeout = TimeOut; } } 

然后简单地

 ((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300); 

如果可以帮助,这是VB.Net解决scheme:

 Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext objectContext.commandTimeout = connectionTimeout 

以下是我在使用EDMX文件时如何解决这个问题。 此解决scheme更改了默认的T4模板,以使生成的类从自定义的DbContext类(它指定默认的命令超时)以及用于更改它的属性inheritance。

我正在使用Visual Studio 2012和EF 5.0。 您的体验可能与其他版本不同。

创build一个自定义的DbContext类

 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; } } } 

这有一个可选的function:我没有硬编码的默认命令超时。 相反,我从项目设置加载它,以便我可以更改configuration文件中的值。 如何设置和使用项目设置不在此答案的范围内。

我也没有硬编码的连接string或连接string名称。 它已经通过生成的上下文类传入构造函数,所以在这里对它进行硬编码是没有意义的。 这不是什么新鲜事。 EDMX文件已经为您生成了以下构造函数,所以我们只是传递值。

 public MyEntities() : base("name=MyEntities") { } 

(这指示EF从configuration文件中加载名为“MyEntities”的连接string。)

如果ObjectContext是空的,我抛出一个自定义exception。 我不认为它会永远是,但它比得到一个NullReferenceException更有意义。

我将ObjectContext存储在一个字段中,这样我可以创build一个属性来访问它来覆盖默认值。

修改实体上下文T4模板

在解决scheme资源pipe理器中,展开EDMX文件,以便看到T4模板。 他们有一个.tt扩展名。

双击“MyModel.Context.tt”文件将其打开。 在第57行左右你应该看到这个:

 <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext 

该模板行生成inheritanceDbContext的“MyEntities”类的类定义。

更改行,以便生成的类inheritanceCustomDbContext,而不是:

 <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext 

只要你保存这个文件,它应该重新生成类。 如果没有,您可以右键单击EDMX文件并select“运行自定义工具”。 如果您在EDMX文件下展开“MyModel.Context.tt”文件,您将看到“MyModel.Context.cs”。 这是生成的文件。 打开它,你会看到它现在inheritance了CustomDbContext

 public partial class MyEntities : CustomDbContext 

这里的所有都是它的。

问题

一旦将上下文类从DbContextCustomDbContext ,如果尝试使用“具有读/写操作和视图的控制器,使用entity framework”模板添加新的MVC控制器类,Visual Studio将会出错。 它会说“不支持的上下文types”。 为了解决这个问题,打开生成的“MyModel.Context.cs”类,并临时将其inheritance的types更改回DbContext 。 添加新控制器后,可以将其更改回CustomDbContext

我来到这里寻找一个设置单个命令超时的例子,而不是这样一个全局设置。

我认为这可能会帮助某个人举例说明我是如何实现这一目标的:

 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(); 
Interesting Posts