web-dev-qa-db-fra.com

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 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.

54
Yara

Cela fonctionnera avec votre méthode. 

Ou sous-classez-le (à 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;
  }
}
88
Jonas Lincoln

Cela peut vous aider.

public class MyContext : DbContext
{    
    public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}
20
Rejeesh
var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;
19
Perry Tribolet

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 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 ensuite apparaître dans votre fichier Context.cs généré:

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

J'aime l'approche par 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
Stefan Michev

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'attente de commande par défaut et une propriété permettant de le modifier.

J'utilise Visual Studio 2012 et EF 5.0. Votre expérience peut différer d'une autre version.

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é optionnelle: je ne code pas en dur le délai d'attente de la commande par défaut. Au lieu de cela, je le charge à partir des paramètres du projet afin de pouvoir modifier la valeur dans un fichier de configuration. Comment configurer et utiliser les paramètres du projet ne fait pas partie de cette réponse.

Je ne code pas non plus en dur 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, il est donc insensé de le coder en dur ici. Ce n'est pas nouveau. le fichier EDMX génère déjà le constructeur suivant pour vous, nous ne faisons donc que transmettre 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 la variable ObjectContext est toujours nulle. Je ne pense pas que ce le sera jamais, mais c'est plus significatif que d'obtenir un NullReferenceException

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

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

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

Double-cliquez sur le fichier "MyModel.Context.tt" 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 devrait régénérer la classe. Sinon, vous pouvez cliquer avec le bouton droit sur le fichier EDMX et sélectionner "Exécuter l'outil personnalisé". 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 de CustomDbContext.

public partial class MyEntities : CustomDbContext

C'est tout ce qu'on peut en dire.

Problèmes

Une fois que vous avez modifié la classe de contexte de DbContext à CustomDbContext, Visual Studio vous signalera une erreur si vous essayez d'ajouter une nouvelle classe de contrôleur MVC à l'aide du modèle "Contrôleur avec actions et vues en lecture/écriture utilisant Entity Framework". Il dira "type de contexte non pris en charge". Pour résoudre ce problème, ouvrez la classe "MyModel.Context.cs" générée et modifiez temporairement le type dont il hérite à DbContext. Après avoir ajouté votre nouveau contrôleur, vous pouvez le remettre à CustomDbContext.

2
Glazed

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

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

Je suis venu ici à la recherche d'un exemple de définition du délai d'attente pour une seule commande plutôt que d'un 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
Elliot Harper