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 ?

James
la source
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

Leniel Maccaferri
la source
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.

Vu Nguyen
la source
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.

Erik Philips
la source
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;
    }
}
Owen
la source
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));
    } 
}
Timmerz
la source
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.

Christian Gollhardt
la source
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;
    }
}
Ronnie Overby
la source
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

Andrew Burrow
la source
0

Vous pouvez utiliser ce simple:
dbContext.Database.SetCommandTimeout(300);

Hassan Muhammad Saad
la source