How to set CommandTimeout for DbContext?

I am looking for a way to set CommandTimeout for a DbContext. After searching, I found a way by placing the DbContext in the ObjectContext and setting the value for the CommandTimeout property of the object.conf object.

var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext; 

But I need to work with DbContext.

+44
c # entity-framework-4 dbcontext
May 11 '12 at 10:26
source share
8 answers

It will work with your method.

Or a subclass (from msdn forum )

 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; } } 
+76
May 11 '12 at 10:30
source share

This can help you.

 public class MyContext : DbContext { public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true) { ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; } } 
+20
May 11 '12 at
source share
 var ctx = new DbContext(); ctx.Database.CommandTimeout = 120; 
+12
Mar 25 '16 at 16:17
source share

I found that modifying the .tt file works for me since I will not lose this change later:

Add this line:

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

Immediately after the creator of the DbContext and before the loader.IsLazy construct:

 <#=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)) 

Then it should appear in the created Context.cs:

 public MyEntities() : base("name=MyEntities") { ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300; } 
+3
Jun 09 '15 at
source share

I like the extension approach:

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

and then just

 ((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300); 
+2
Dec 29 '15 at 17:20
source share

This is how I solved this problem when using the EDMX file. This solution modifies the default T4 template to make the generated class inherit from the custom DbContext class, which indicates the default command timeout and the property to change it.

I am using Visual Studio 2012 and EF 5.0. Your experience may vary in other versions.

Create your own DbContext class

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

This has an additional function: I do not hardcode the default command timeout. Instead, I load it from the project settings to change the value in the configuration file. How to configure and use project settings is not included in the scope of this answer.

I also do not hardcode the connection string or the name of the connection string. He has already moved to the constructor with the generated context class, so there is no point in hard-coding it. This is nothing new; The EDMX file already generates the following constructor for you, so we just pass the value.

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

(This instructs EF to load the configuration line named "MyEntities" from the configuration file.)

I throw a special exception if the ObjectContext always null. I don't think it will ever be, but it is more meaningful than getting a NullReferenceException .

I store an ObjectContext in a field so that I can make a property to access it to override the default value.

Changing the T4 Object Context Template

In Solution Explorer, expand the EDMX file so that you can see the T4 templates. They have the extension .tt.

Double-click the file "MyModel.Context.tt" to open it. On line 57 you should see this:

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

This template line generates a class definition for your class "MyEntities", which inherits DbContext.

Modify the line so that the generated class inherits CustomDbContext, instead:

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

Once you save this file, it should restore the class. If not, you can right-click the EDMX file and select Run Custom Tool. If you expand the file "MyModel.Context.tt" under your EDMX file, you will see "MyModel.Context.cs". This is a generated file. Open it and you will see that it now inherits CustomDbContext .

 public partial class MyEntities : CustomDbContext 

That is all that is needed.

Questions

After changing the context class from DbContext to CustomDbContext , Visual Studio will give you an error message if you try to add a new MVC controller class using “Controller with read / write actions and views using the Entity Framework.” It will say “Unsupported context type” To work around this, open the generated class "MyModel.Context.cs" and temporarily change the type inherited to DbContext . After adding a new controller, you can change it to CustomDbContext .

+2
Jun 05 '15 at 15:26
source share

If this can help, this is VB.Net solution:

 Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext objectContext.commandTimeout = connectionTimeout 
+1
Mar 26 '13 at 10:27
source share

I came here to find an example of setting a timeout for one command, and not such a global setting.

I believe this will probably help someone give an example of how I achieved this:

 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(); 
0
Aug 12 '16 at 9:20
source share



All Articles