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.

107voto

Jonas Lincoln Points 4330

Cela fonctionnera avec votre méthode.

Ou le sous-classer (à 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;
  }
}

20 votes

Quel est l'intérêt d'utiliser as ? Cela ne va-t-il pas transformer un InvalidCastException en un NullReferenceException ? Je pense que la première réponse est beaucoup plus claire.

0 votes

Existe-t-il un moyen de définir ce paramètre à partir d'une classe partielle ? Je travaille avec des fichiers EDMX et je veux éviter que cela soit écrasé chaque fois que je modifie le modèle.

2 votes

Voir la solution de Perry Tribolet. Beaucoup plus simple.

45voto

Perry Tribolet Points 827
var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;

21voto

Rejeesh Points 327

Cela peut vous aider.

public class MyContext : DbContext
{    
    public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}

10voto

Mike Burger Points 191

Je trouve que la modification du fichier .tt fonctionne pour moi, car je ne perds pas la modification par la suite :

Ajoutez cette ligne :

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

Juste après le créateur de DbContext et avant la construction !loader.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 Context.cs généré :

public MyEntities()
            : base("name=MyEntities")
        {
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
        }

3voto

Glazed Points 865

Voici comment j'ai résolu ce problème en utilisant un fichier EDMX. Cette solution change 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 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 être différente 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;
        }
    }
}

Il s'agit d'une fonction optionnelle : Je ne code pas en dur le délai de 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. La façon de configurer et d'utiliser les paramètres du projet n'entre pas dans le cadre de cette réponse.

Je ne fais pas non plus de codage en dur de la chaîne de connexion ou du nom de la chaîne de connexion. Ils sont déjà passés dans le constructeur par la classe de contexte générée, il n'y a donc aucun sens à les coder en dur ici. Il n'y a rien de nouveau ; le fichier EDMX génère déjà le constructeur suivant pour vous, donc nous ne faisons que transmettre la valeur.

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

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

Je lève une exception personnalisée si le fichier ObjectContext est toujours nulle. Je ne pense pas qu'il le sera un jour, mais c'est plus significatif que d'obtenir un message de type NullReferenceException .

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

Modifier le contexte de l'entité Modèle T4

Dans l'explorateur de solutions, développez le fichier EDMX de manière à voir les modèles T4. Ils portent une extension .tt.

Double-cliquez sur le fichier "MyModel.Context.tt" pour l'ouvrir. A 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 votre classe "MyEntities", qui hérite de DbContext.

Changez 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, la classe est régénérée. Si ce n'est pas le cas, vous pouvez cliquer avec le bouton droit de la souris sur le fichier EDMX et sélectionner "Run Custom Tool". Si vous développez le fichier "MyModel.Context.tt" sous votre fichier EDMX, vous verrez "MyModel.Context.cs". C'est le fichier généré. Ouvrez-le, et vous devriez voir qu'il hérite maintenant des éléments suivants 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 a CustomDbContext Si vous essayez d'ajouter une nouvelle classe de contrôleur MVC en utilisant le modèle "Controller with read/write actions and views, using Entity Framework", Visual Studio vous donnera une erreur. Il vous dira "Unsupported context type.". Pour contourner ce problème, ouvrez la classe générée "MyModel.Context.cs" et changez temporairement le type dont elle hérite en DbContext . Après avoir ajouté votre nouveau contrôleur, vous pouvez le changer à nouveau en CustomDbContext .

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