How to set command timeout in ASP.NET Core / Entity Framework Core?
Asked Answered
C

5

114

The place where the command timeout is set is no longer the same as earlier versions.

However, I cannot find anywhere that says how to change this.

What I am doing is uploading very large files which takes longer than the default 30 seconds to save.

Note that I ask about command timeout, not migration timeout as in another question.

Cynthiacynthie answered 20/8, 2016 at 20:25 Comment(2)
Take a look at How to set Entity Framework Core migration timeout? - the answer with Database.SetCommandTimeoutDimerous
Possible duplicate of How to set Entity Framework Core migration timeout?Headphone
T
214

If you're using the DI container to manage the DbContext (i.e. you're adding the DbContext to the service collection), the command timeout can be specified in the options.

In Startup.ConfigureServices:

services.AddDbContext<YourDbContext>(options => options.UseSqlServer(
    this.Configuration.GetConnectionString("YourConnectionString"),
    sqlServerOptions => sqlServerOptions.CommandTimeout(60))
);
Tabriz answered 15/11, 2017 at 17:2 Comment(5)
This is most reasonable approach, uses built in configuration APIs, configuration is decoupled and easy to change, is part of class responsible for configiration. All other offets are sort of hacks.Deathlike
Does not seem to work anymore in .NET 6/EF6 - There is no method CommandTImeout, SetCommandTimeout or anything like that.Grassgreen
@Aileron79, the example provided uses Entity Framework Core, not Entity Framework 6.Acorn
Note you have to add 'using Microsoft.EntityFrameworkCore' to the top of your file to get this extension method.Mansuetude
I can't imagine this being the best solution for most people needing to do this. If you need to increase timeout it's most likely because you have a small subset of queries that are expected to timeout with the defaults (for whatever reason - not judging!). If the rest of your queries are all perfectly optimized you could use a timeout of 1 day and never notice, but this takes away the database's ability to complain for those queries you don't yet know are inefficient. Bigger issue for larger timeouts (eg 5 mins) Consider other answers first, don't be quick to find a fix you may regret later.Yen
Z
75

you can change it through your context

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext()
    {
        Database.SetCommandTimeout(150000);
    }
}
Zinck answered 1/9, 2017 at 6:37 Comment(2)
That's not work for EF6 Core. Or maybe I do something else. I mean that SaveChanges() is executed for example for 10 seconds, when I set timeout for 1 second it still not throws error, maybe You know how to set this?Sybyl
Note: If you're setting the timeout on the Database property of an injected context make sure you add using Microsoft.EntityFrameworkCore; since SetCommandTimeout is an extension method.Yen
D
45

If you would like a temporary increase timeout only for one Context instance.

Let's say for 1 request (default Scoped context lifetime)

Change this before long running query:

Context.Database.SetCommandTimeout(TimeSpan.FromMinutes(20))

With scoped lifetime you can specify timeout only once and you do not have to specify it in any subsequent services constructors injections.

Demonize answered 16/4, 2021 at 0:31 Comment(3)
Thanks for your answer which specifically addressed my concern about the lifetime of making such a change. However, I am curious as to how you know the value used in SetCommandTimeout is scoped only to the one context provided via DI and not to every instance of the context? Do you have a reference to documentation to support this?Piles
where should I put this line? Inside controllers IActionResult, inside using of dbContext statement, inside constructor of dbContext?Caniff
@Blair good question! The docs for DbContext.Database specifically say Creates a Database instance **for this context** that allows for creation/deletion/existence checks for the underlying database., so yes it is just for one context. learn.microsoft.com/en-us/dotnet/api/…Yen
W
18

In EF Core 3 and above, you can now configure this via connection string. But you need to migrate from 'System.Data.SqlClient' to 'Microsoft.Data.SqlClient'.

Replace System.Data.SqlClient with Microsoft.Data.SqlClient version 2.1.0 or greater.

Then in your connection string simply append the command timeout like so:

"Data Source=SqlExpress;Initial Catalog=YourDatabase;Integrated Security=true;Command Timeout=300"

This will only work with Microsoft.Data.SqlClient 2.1.0 or above, you will get exception if you try this with System.Data.SqlClient.

Weft answered 24/6, 2021 at 1:27 Comment(2)
Beware 4.0 breaking change, Encrypt=true is now default, before that and System..SqlClient does not attempt TLS for mssql connections by default. github.com/dotnet/SqlClient/blob/main/…Washerman
Encrypt=true can cause connections to start failing if servers use internal certs, or if you're connecting to domain-joined servers from outside the domain, in my case for Kubernetes hosted apps.Washerman
I
7

The better option is to use CommandTimeout during your context setup like:

public class DbConnect: IConnnectDb
{
    private dbentitient _context;

    // inject this to a db entity from constructor. 

    //inside each method now use the follow before u actually run the query to db.  

    _context.Database.SetCommandTimeout(400);
}     

Note: EF Core will only execute the query with less than 100 seconds time. If it's more than that it keeps retrying and you never get to see the result.

That's my experience as of now, so let me know if you are able to fix it EF Core 1.0 does timeout even more fast than EF Core 2.0.

Incurrence answered 20/9, 2017 at 22:3 Comment(1)
This doesn't seem to be right. EF Core doesn't retry anything by default?Disquisition

© 2022 - 2024 — McMap. All rights reserved.