180

My command keeps timing out, so I need to change the default command timeout value.

I've found myDb.Database.Connection.ConnectionTimeout, but it's readonly.

How can I set the command timeout in Entity Framework 5 ?

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
James
  • 2,811
  • 3
  • 25
  • 29
  • 20
    FYI, On EF6, `Database.CommandTimeout` is no longer read-only – itsho Jun 25 '14 at 21:33
  • 2
    @itsho He was talking about `Database.Connection.ConnectionTimeout`. Anyway, I would say that `Database.CommandTimeout` is the right thing in the case your query is time-outing (exception `System.Data.Entity.Core.EntityCommandExecutionException` containing `System.Data.SqlClient.SqlException: Timeout expired.`). – David Ferenczy Rogožan Mar 04 '16 at 14:59
  • 3
    Possible duplicate of [Entity Framework Timeouts](http://stackoverflow.com/questions/6232633/entity-framework-timeouts) – Tim Pohlmann Dec 01 '16 at 10:05
  • 2
    I assume you actually don't care about the CONNECTION timeout, but instead you want to adjust the COMMAND timeout. – Worthy7 Aug 18 '17 at 06:18

11 Answers11

220

Try this on your context:

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

If you want to define the timeout in the connection string, use the Connection Timeout parameter like in the following connection string:

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

Source: How to: Define the Connection String

Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 1
    I would recommend using the connection string version as if you try to access the `ObjectContext` in this constructor sometimes the [PowerShell/NuGet console commands will fail in a circular way](http://stackoverflow.com/questions/15169281/receiving-the-model-backing-the-context-context-has-changed-on-add-migrati). – Kevin Gorski Mar 05 '13 at 18:24
  • 144
    Connection Timeout and CommandTimeout and two separate things. The connection string setting, Connection Timeout, won't affect the amount of time the command runs (CommandTimeout). – Clay Lenhart Jul 25 '13 at 11:01
  • Might be because this is an answer is a year old but `Connection Timeout` raises an `EntityException` "The underlying provider failed on Open". The actual valid value is `Connect Timeout` but it appears to be ignored by EF anyway. – user692942 Dec 03 '13 at 11:02
  • 3
    My problem was a litte different. I got timeout during migrations. EF has a similar property to set for using during migrations: http://msdn.microsoft.com/en-us/library/system.data.entity.migrations.dbmigrationsconfiguration.commandtimeout – Karsten Aug 14 '14 at 07:42
  • 2
    Depending on what version of EF you use, see [this answer](http://stackoverflow.com/a/6234593/2874896) to get a feeling about the different API's in how to specify the CommandTimeout property. – Jim Aho Oct 09 '14 at 08:22
  • 1
    Does not work for me (Connection vs Command not being teh same thing I suspect). This post solved it though http://stackoverflow.com/questions/6232633/entity-framework-timeouts – Jezbers Jul 17 '15 at 15:34
  • 1
    My Connection Timeout was set OK but discovered `CommandTimeout` was null. I set `CommandTimeout` as per @leniel-macaferi 's suggestion and it solved my timeout issue. -So they are not the same thing and both need to be set to enable a custom timeout to be set in EF. – Nebu Mar 02 '16 at 00:03
  • 1
    @Karsten - thanks for the tip about dbmigrationsconfiguration! I would have tinkered with the context command timeout until the cows come home. – cdonner Mar 31 '16 at 23:41
  • 1
    The connection string solution leads to "Keyword not supported: 'connection timeout'." – Thomas Hahn Mar 22 '17 at 11:47
  • Yes these are 2 different things command timeout and connection timeout. command timeout is what you want not connection timeout – Andrew Jun 19 '19 at 09:49
201

You can use DbContext.Database.CommandTimeout = 180; // seconds

It's pretty simple and no cast required.

Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
Vu Nguyen
  • 3,605
  • 3
  • 22
  • 34
21

My partial context looks like:

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

I left SetCommandTimeOut public so only the routines I need to take a long time (more than 5 minutes) I modify instead of a global timeout.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
10

In the generated constructor code it should call OnContextCreated()

I added this partial class to solve the problem:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}
Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62
Owen
  • 4,229
  • 5
  • 42
  • 50
9

I extended Ronnie's answer with a fluent implementation so you can use it like so:

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));
    } 
}
Timmerz
  • 6,090
  • 5
  • 36
  • 49
9

For Database first Aproach:

We can still set it in a constructor, by override the ContextName.Context.tt T4 Template this way:

<#=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; is the acutaly change.

The generated output is this:

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

If you change your Database Model, this template stays, but the actualy class will be updated.

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • Is there way we can specify timeout in Template using some config file.? – shas Sep 14 '16 at 12:33
  • 1
    not sure, if there something build in (I wasn't able to find something). But instead of hardcoding 180, you can use [`System.Configuration.ConfigurationManager.AppSettings["keyname"]`](http://stackoverflow.com/questions/1189364/reading-settings-from-app-config-or-web-config-in-net) @shas – Christian Gollhardt Sep 14 '16 at 12:41
8

Same as other answers, but as an extension method:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346
1

You can use this simple :
dbContext.Database.SetCommandTimeout(300);

1

I just ran in to this problem and resolved it by updating my application configuration file. For the connection in question, specify "Connection Timeout=60" (I am using entity framework version 5.0.0.0)

ConnectionTimeout Setting

0

In my case the Connection string property is readonly. Also, the entities constructor is autogenerated so I didn't want to put it in there. Plus, putting in the constructor applied to all and I only needed it on one sproc.

Below is my workaround

try
     { using (MyEntities Mydb = new MyEntities())
       {
         (Mydb as System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext.CommandTimeout = 600;
         Mydb.LongRunningSproc();
        }
      }
  catch (System.Data.Common.DbException ex)
      {
          throw new Exception(SomeMessageHere);
      }
Bob Sheehan
  • 160
  • 1
  • 6
-2

You should make the changes in the Connection String tag in the web config and make the EntityFrameWork read from it in its contructor.

  1. Add this term to the web.config Connection String: Connection Timeout=300;

  2. Add the following code in the constructor:

    Database.CommandTimeout = Database.Connection.ConnectionTimeout;

By this approach you will make the user able to control the time out without make a new publish for him.

  • 1
    As noted earlier: connection timeout != command timeout. Command timeout is what matters here. – Gert Arnold Apr 02 '21 at 08:54
  • This approach was to read it dynamically from the Connection String rather than making a separate setting for it. – Wael Galal El Deen Apr 07 '21 at 08:10
  • That detail escaped my eye, and that immediately shows the problem with such hacks. It's totally unexpected and should never be done. – Gert Arnold Apr 07 '21 at 08:18
  • The hacking checks should be done from other places and I thing the command time out of the command should be long enough to execute long queries or SQL commands. So the admin of the website should be able to control this period according to his needs without getting a new publish for just changing the command time out period. – Wael Galal El Deen Apr 14 '21 at 10:51
  • NOT by abusing the *Connection Timeout* setting in the connection string! The next application manager will set it to some other value, unaware of its implications. And, remember, it *also* sets the connection timeout (obviously). You don't want people to wait for 5 minutes if the connection happens to be unavailable due to some contingency. – Gert Arnold Apr 14 '21 at 11:54