Définir le délai d'expiration de la base de données dans Entity Framework


164

Ma commande continue d'expirer, je dois donc modifier la valeur de délai d'expiration de la commande par défaut.

J'ai trouvé myDb.Database.Connection.ConnectionTimeout, mais c'est readonly.

Comment puis-je définir le délai d'expiration de la commande dans Entity Framework 5 ?


20
FYI, sur EF6, Database.CommandTimeoutn'est plus en lecture seule
itsho

2
@itsho dont il parlait Database.Connection.ConnectionTimeout. Quoi qu'il en soit, je dirais que Database.CommandTimeoutc'est la bonne chose dans le cas où votre requête est expirée (exception System.Data.Entity.Core.EntityCommandExecutionExceptioncontenant System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan

2
Possible duplicate of Entity Framework Timeouts
Tim Pohlmann

1
Je suppose que vous ne vous souciez pas du délai de CONNEXION, mais à la place, vous souhaitez ajuster le délai de COMMANDE.
Worthy7

Réponses:


199

Essayez ceci dans votre contexte:

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

Si vous souhaitez définir le délai d'expiration dans la chaîne de connexion, utilisez le Connection Timeoutparamètre comme dans la chaîne de connexion suivante:

<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: Comment: définir la chaîne de connexion


1
Je recommanderais d'utiliser la version de la chaîne de connexion comme si vous essayez d'accéder à ObjectContextdans ce constructeur, parfois les commandes de la console PowerShell / NuGet échouent de manière circulaire .
Kevin Gorski

130
Connection Timeout et CommandTimeout et deux choses distinctes. Le paramètre de chaîne de connexion, Délai de connexion, n'affectera pas la durée d'exécution de la commande (CommandTimeout).
Clay Lenhart

3
Mon problème était un peu différent. J'ai eu un délai pendant les migrations. EF a une propriété similaire à définir pour une utilisation pendant les migrations: msdn.microsoft.com/en-us/library
Karsten

2
En fonction de la version d'EF que vous utilisez, consultez cette réponse pour avoir une idée des différentes API et savoir comment spécifier la propriété CommandTimeout.
Jim Aho

1
Ne fonctionne pas pour moi (Connection vs Command n'étant pas la même chose que je soupçonne). Ce message l'a résolu
via

181

Vous pouvez utiliser DbContext.Database.CommandTimeout = 180;

C'est assez simple et aucun casting n'est requis.


1
Très utile pour nous qui utilisons la Fluent APIforme d'EF.
GoldBishop

20

Mon contexte partiel ressemble à:

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

J'ai laissé SetCommandTimeOutpublic donc seules les routines dont j'ai besoin pour prendre beaucoup de temps (plus de 5 minutes) que je modifie au lieu d'un timeout global.


9

Dans le code du constructeur généré, il doit appeler OnContextCreated()

J'ai ajouté cette classe partielle pour résoudre le problème:

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

8

J'ai étendu la réponse de Ronnie avec une implémentation fluide pour que vous puissiez l'utiliser comme ceci:

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

8

Pour la première approche de la base de données:

Nous pouvons toujours le définir dans un constructeur, en remplaçant le modèle ContextName.Context.tt T4 de cette façon:

<#=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; est le changement réel.

La sortie générée est la suivante:

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

Si vous modifiez votre modèle de base de données, ce modèle reste, mais la classe actuelle sera mise à jour.


Existe-t-il un moyen de spécifier le délai d'expiration dans le modèle en utilisant un fichier de configuration.?
shas

1
pas sûr, s'il y avait quelque chose à intégrer (je n'ai pas pu trouver quelque chose). Mais au lieu de coder en dur 180, vous pouvez utiliser System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Christian Gollhardt

7

Identique aux autres réponses, mais comme méthode d'extension:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}

et comment appeler cette méthode d'extension?
Wanderson López

1

Je viens de rencontrer ce problème et je l'ai résolu en mettant à jour le fichier de configuration de mon application. Pour la connexion en question, spécifiez "Connection Timeout = 60" (j'utilise la version 5.0.0.0 du framework d'entité)

Paramètre ConnectionTimeout


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.