Establecer el tiempo de espera de la base de datos en Entity Framework

164

Mi comando sigue agotando el tiempo de espera, por lo que necesito cambiar el valor predeterminado del tiempo de espera del comando.

Lo he encontrado myDb.Database.Connection.ConnectionTimeout, pero lo es readonly.

¿Cómo puedo configurar el tiempo de espera del comando en Entity Framework 5 ?

James
fuente
20
FYI, en EF6, Database.CommandTimeoutya no es de solo lectura
es el
2
@itsho estaba hablando Database.Connection.ConnectionTimeout. De todos modos, diría que Database.CommandTimeoutes lo correcto en el caso de que su consulta sea de tiempo de espera (que System.Data.Entity.Core.EntityCommandExecutionExceptioncontiene una excepción System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan
2
Posible duplicado de los tiempos de espera
Tim Pohlmann, del
1
Supongo que en realidad no le importa el tiempo de espera de CONEXIÓN, pero en su lugar desea ajustar el tiempo de espera de COMANDO.
Digno7

Respuestas:

199

Prueba esto en tu contexto:

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

Si desea definir el tiempo de espera en la cadena de conexión, use el Connection Timeoutparámetro como en la siguiente cadena de conexión:

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

Fuente: Cómo: definir la cadena de conexión

Leniel Maccaferri
fuente
1
Recomendaría usar la versión de cadena de conexión como si intentara acceder ObjectContexta este constructor, a veces los comandos de la consola PowerShell / NuGet fallarán de forma circular .
Kevin Gorski
130
Connection Timeout y CommandTimeout y dos cosas separadas. La configuración de la cadena de conexión, Tiempo de espera de conexión, no afectará la cantidad de tiempo que se ejecuta el comando (CommandTimeout).
Clay Lenhart
3
Mi problema fue un poco diferente. Tengo tiempo de espera durante las migraciones. EF tiene una propiedad similar para configurar durante las migraciones: msdn.microsoft.com/en-us/library/…
Karsten
2
Dependiendo de la versión de EF que use, vea esta respuesta para tener una idea de las diferentes API sobre cómo especificar la propiedad CommandTimeout.
Jim Aho
1
No funciona para mí (Connection vs Command no es lo mismo que sospecho). Esta publicación lo resolvió aunque stackoverflow.com/questions/6232633/entity-framework-timeouts
Jezbers
181

Puedes usar DbContext.Database.CommandTimeout = 180;

Es bastante simple y no requiere yeso.

Vu Nguyen
fuente
1
Muy útil para nosotros que usan la Fluent APIforma de EF.
GoldBishop
20

Mi contexto parcial se ve así:

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

Dejé SetCommandTimeOutpúblico, por lo que solo modifico las rutinas que necesito tomar mucho tiempo (más de 5 minutos) en lugar de un tiempo de espera global.

Erik Philips
fuente
9

En el código de constructor generado debería llamar OnContextCreated()

Agregué esta clase parcial para resolver el problema:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}
Owen
fuente
8

Extendí la respuesta de Ronnie con una implementación fluida para que puedas usarla así:

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

Para la base de datos primero Aproach:

Todavía podemos configurarlo en un constructor, anulando la plantilla ContextName.Context.tt T4 de esta manera:

<#=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; Es el cambio acutal.

La salida generada es esta:

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

Si cambia su Modelo de base de datos, esta plantilla permanece, pero la clase actual se actualizará.

Christian Gollhardt
fuente
¿Hay alguna manera de que podamos especificar el tiempo de espera en la plantilla usando algún archivo de configuración?
shas
1
no estoy seguro, si hay algo incorporado (no pude encontrar algo). Pero en lugar de codificar 180, puede usar System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Christian Gollhardt el
7

Igual que otras respuestas, pero como método de extensión:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}
Ronnie Overby
fuente
¿Y cómo llamo a este método de extensión?
Wanderson López
1

Acabo de encontrarme con este problema y lo resolví actualizando el archivo de configuración de mi aplicación. Para la conexión en cuestión, especifique "Tiempo de espera de conexión = 60" (estoy usando la versión de Framework 5.0.0.0 de la entidad)

ConnectionTimeout Setting

Andrew Burrow
fuente
0

Puedes usar este simple:
dbContext.Database.SetCommandTimeout(300);

Hassan Muhammad Saad
fuente