79 votes

Comment définir CommandTimeout pour DbContext ?

Je cherche un moyen de définir CommandTimeout pour DbContext. Après avoir cherché, j'ai trouvé le moyen de transformer DbContext en ObjectContext et de définir la valeur de la propriété CommandTimeout d'objectContext.

var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;

Mais je dois travailler avec DbContext.

2voto

Stefan Michev Points 131

J'aime l'approche de l'extension :

public static class DbContextExtensions
{
   public static void SetCommandTimeout(this ObjectContext dbContext,
       int TimeOut)
   {
       dbContext.CommandTimeout = TimeOut;
   }
}

et ensuite simplement

((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);

1voto

Dave Points 19

C'est similaire à l'approche utilisée par @Glazed ci-dessus, mais mon approche consiste également à utiliser une classe DbContext personnalisée, mais je fais l'inverse. Au lieu de modifier le modèle T4 (fichier .tt sous votre .edmx), j'hérite en fait de la classe MyEntities résultante, comme suit :

Classe MyEntities générée par le modèle T4 :

public partial class MyEntities : DbContext
{
    public MyEntities()
        : base("name=MyConnectionStringName")
    {
    }
...
}

Créez ensuite une nouvelle classe personnalisée pour envelopper MyEntities comme suit :

public class MyEntitiesContainer : MyEntities
{
    private static readonly int _DEFAULT_TIMEOUT = 100;
    public MyEntitiesContainer()
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = _DEFAULT_TIMEOUT;
    }

    //Use this method to temporarily override the default timeout
    public void SetCommandTimeout(int commandTimeout)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = commandTimeout;
    }

    //Use this method to reset the timeout back to default
    public void ResetCommandTimeout()
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = _COMMAND_TIMEOUT;
    }
}

Dans votre code, instanciez la classe Container et si vous devez utiliser un délai d'attente personnalisé pour une commande spécifique, définissez-le manuellement à l'aide des méthodes fournies.

using (var db = new MyEntitiesContainer()) {
    db.SetCommandTimeout(300);
    db.DoSomeLongCommand();
    db.ResetCommandTimeout();
    db.DoShorterCommand1();
    db.DoShorterCommand2();
    ...
}

L'avantage de cette approche est que vous pouvez également créer une interface pour votre classe Container et utiliser des instances de l'interface avec l'injection de dépendances, vous pouvez alors simuler votre base de données dans vos tests unitaires en plus d'avoir un contrôle plus facile sur le délai de commande et d'autres propriétés du contexte objet pour lesquelles vous pouvez créer des méthodes (comme le chargement paresseux, etc.).

1voto

Exatex Points 74

Si cela peut vous aider, voici la solution VB.Net :

Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout

0voto

Elliot Harper Points 19

Je suis venu ici pour trouver un exemple de réglage du délai d'attente pour une seule commande plutôt qu'un réglage global.

Je me suis dit que cela aiderait probablement quelqu'un d'avoir un exemple de la façon dont j'y suis parvenu :

var sqlCmd = new SqlCommand(sql, context.Database.Connection as SqlConnection);
sqlCmd.Parameters.Add(idParam);
sqlCmd.CommandTimeout = 90;

if (sqlCmd.Connection.State == System.Data.ConnectionState.Closed)
{
    sqlCmd.Connection.Open();
}
sqlCmd.ExecuteNonQuery();
sqlCmd.Connection.Close();

0voto

Zeek2 Points 125

La réponse de @PerryTribolet semble bonne pour EF6 mais elle fonctionne pour EF5. Pour EF, voici une façon de procéder : créer un ObjectContext, définir le CommandTimeout sur celui-ci, puis créer un DBContext à partir de l'ObjectContext. J'ai activé le drapeau pour que les deux objets soient éliminés ensemble. Voici un exemple en VB.NET :

        Dim context As New ObjectContext("name=Our_Entities")
        Dim dbcontext As New System.Data.Entity.DbContext(context, True)

        With context
            .CommandTimeout = 300 'DBCommandTimeout
        End With

Vous n'êtes pas obligé d'utiliser "Avec", bien sûr.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X