我在寻找一种方法来设置的CommandTimeout为的DbContext。 搜索后,我被铸造成的DbContext ObjectContext的和ObjectContext中的CommandTimeout属性设定值中发现的方式。
var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;
但是我有的DbContext工作。
我在寻找一种方法来设置的CommandTimeout为的DbContext。 搜索后,我被铸造成的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右后和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;
}
下面是使用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")
{
}
(这指示EF加载从配置文件命名为“MyEntities”的连接字符串。)
我抛出一个自定义异常,如果ObjectContext
是有史以来空。 我不认为这永远不会是,但它比得到一个更有意义NullReferenceException
。
我保存ObjectContext
在一个领域,这样我可以做一个属性来访问它来替代默认。
在解决方案资源管理器中,展开EDMX文件,以便您看到T4模板。 他们有一个.TT扩展。
双击“MyModel.Context.tt”文件将其打开。 大约57行,你应该看到这一点:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
此模板行生成你的“MyEntities”类,它继承的DbContext的类定义。
更改行,这样生成的类继承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
,如果你尝试添加使用新的MVC控制器类“控制器,具有读/写操作和视图,使用实体框架”模板的Visual Studio会给你一个错误。 它会说“不支持的上下文类型。” 为了解决这个问题,打开生成的“MyModel.Context.cs”类,并暂时更改它继承回类型DbContext
。 添加新的控制器后,您可以改回CustomDbContext
。
我喜欢的推广方法:
public static class DbContextExtensions
{
public static void SetCommandTimeout(this ObjectContext dbContext,
int TimeOut)
{
dbContext.CommandTimeout = TimeOut;
}
}
然后简单地
((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);
如果它可以帮助,这是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();