Comment définir CommandTimeout pour DbContext?

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

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

Mais je dois travailler avec DbContext.

50
demandé sur Yara 2012-05-11 14:26:37

8 réponses

Cela fonctionnera avec votre méthode.

Ou sous-classe (à partir de forum msdn)

public class YourContext : DbContext
{
  public YourContext()
    : base("YourConnectionString")
  {
    // Get the ObjectContext related to this DbContext
    var objectContext = (this as IObjectContextAdapter).ObjectContext;

    // Sets the command timeout for all the commands
    objectContext.CommandTimeout = 120;
  }
}
83
répondu Jonas Lincoln 2012-05-11 10:30:59

Cela peut vous aider.

public class MyContext : DbContext
{    
    public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}
20
répondu Rejeesh 2012-05-23 18:42:21
var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;
18
répondu Perry Tribolet 2016-03-25 16:17:29

Je trouve que changer le fichier. tt fonctionne pour moi car je ne perds pas le changement plus tard:

Ajouter cette ligne:

((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;

Juste après le créateur DbContext et avant le!chargeur.Construction IsLazy:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
<#
if (!loader.IsLazyLoadingEnabled(container))

Il devrait alors apparaître dans votre contexte généré.cs:

public MyEntities()
            : base("name=MyEntities")
        {
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
        }
6
répondu Mike Burger 2017-04-25 16:42:30

J'aime l'approche d'extension:

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

Et puis simplement

((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);
2
répondu Stefan Michev 2014-12-29 17:33:08

Voici comment j'ai résolu ce problème lors de l'utilisation d'un fichier EDMX. Cette solution modifie le modèle T4 par défaut pour que la classe générée hérite d'une classe DbContext personnalisée, qui spécifie un délai d'expiration de commande par défaut et une propriété pour le modifier.

J'utilise Visual Studio 2012 et EF 5.0. Votre expérience peut différer avec d'autres versions.

Créer une classe DbContext personnalisée

public class CustomDbContext : DbContext
{
    ObjectContext _objectContext;

    public CustomDbContext( string nameOrConnectionString )
        : base( nameOrConnectionString )
    {
        var adapter = (( IObjectContextAdapter) this);

        _objectContext = adapter.ObjectContext;

        if ( _objectContext == null )
        {
            throw new Exception( "ObjectContext is null." );    
        }

        _objectContext.CommandTimeout = Settings.Default.DefaultCommandTimeoutSeconds;
    }

    public int? CommandTimeout
    {
        get
        {
            return _objectContext.CommandTimeout;
        }
        set
        {
            _objectContext.CommandTimeout = value;
        }
    }
}

Cela a une fonctionnalité facultative: Je ne Code pas en dur le délai d'expiration de la commande par défaut. Au lieu de cela, je le charge à partir des paramètres du projet afin que je puisse changer la valeur dans un fichier de configuration. Comment configurer et utiliser les paramètres du projet n'est pas dans le cadre de cette réponse.

Je ne Code pas non plus la chaîne de connexion ou le nom de la chaîne de connexion. Il est déjà passé dans le constructeur par la classe de contexte générée, donc cela n'a aucun sens de le coder en dur ici. Ce n'est rien de nouveau; le fichier EDMX génère déjà le constructeur suivant pour vous, donc nous passons juste le long de la valeur.

public MyEntities()
    : base("name=MyEntities")
{
}

(Ceci indique à EF de charger la chaîne de connexion nommée "MyEntities" à partir du fichier de configuration.)

Je lance une exception personnalisée si le ObjectContext est jamais null. Je ne pense pas que ce sera jamais le cas, mais c'est plus significatif que d'obtenir un NullReferenceException.

Je stocke le ObjectContext dans un champ afin que je puisse créer une propriété pour y accéder pour remplacer la valeur par défaut.

Modification du modèle T4 de contexte d'entité

Dans L'Explorateur de solutions, développez le fichier EDMX que vous voyez les modèles T4. Ils ont une .tt extension.

Double-cliquez sur "MyModel.Context.tt" fichier pour l'ouvrir. Autour de la ligne 57, vous devriez voir ceci:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext

Cette ligne de modèle génère la définition de classe de votre classe" MyEntities", qui hérite de DbContext.

Modifiez la ligne pour que la classe générée hérite de CustomDbContext, à la place:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext

Dès Que vous enregistrez ce fichier, il doit régénérer la classe. Si ce n'est pas le cas, vous pouvez cliquer avec le bouton droit sur L'EDMX fichier et sélectionnez "Exécuter l'Outil Personnalisé". Si vous développez le "MyModel.Context.tt" fichier sous votre fichier EDMX, vous verrez " MyModel.Cadre.cs". C'est le fichier généré. Ouvrez-le, et vous devriez voir qu'il hérite maintenant de CustomDbContext.

public partial class MyEntities : CustomDbContext

C'est tout ce qu'il y a à faire.

Questions

Une fois que vous avez changé la classe de contexte de DbContext à CustomDbContext, Visual Studio vous donnera une erreur si vous essayez d'ajouter une nouvelle classe de contrôleur MVC en utilisant le " contrôleur avec des actions et des vues en lecture/écriture, en utilisant Modèle "Entity Framework". Il dira " type de contexte non pris en charge.". Pour contourner cela, ouvrez le "MyModel" généré.Cadre.cs" classe, et changer temporairement le type qu'il hérite à DbContext. Après avoir ajouté votre nouveau contrôleur, vous pouvez le changer à CustomDbContext.

2
répondu Glazed 2015-06-05 17:21:00

Si cela peut aider, c'est le VB.Net solution:

Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout
1
répondu Exatex 2013-03-26 10:27:57

Je suis venu ici à la recherche d'un exemple de réglage du délai d'attente pour une seule commande plutôt que d'un tel paramètre global.

Je pense que cela aidera probablement quelqu'un à avoir un exemple de la façon dont j'ai réalisé ceci:

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();
0
répondu Elliot Harper 2016-08-12 09:20:50