Comment définir CommandTimeout pour DbContext?

Je cherche un moyen de définir CommandTimeout pour DbContext. Après avoir effectué une 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.

Cela fonctionnera avec votre méthode.

Ou sous-classe (à partir du forum msdn )

 public class YourContext : DbContext { public YourContext() : base("YourConnectionSsortingng") { // Get the ObjectContext related to this DbContext var objectContext = (this as IObjectContextAdapter).ObjectContext; // Sets the command timeout for all the commands objectContext.CommandTimeout = 120; } } 

Cela peut vous aider.

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

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

Ajoutez cette ligne:

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

Juste après le créateur 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; } 

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); 

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é pour le modifier.

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

Créer une classe DbContext personnalisée

 public class CustomDbContext : DbContext { ObjectContext _objectContext; public CustomDbContext( ssortingng nameOrConnectionSsortingng ) : base( nameOrConnectionSsortingng ) { 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; } } } 

Cette fonctionnalité est facultative: je ne codifie pas le délai d’expiration de la commande par défaut. Au lieu de cela, je le charge à partir des parameters du projet afin que je puisse modifier la valeur dans un fichier de configuration. Comment configurer et utiliser les parameters du projet n’est pas dans la scope de cette réponse.

Je ne codifie 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, il est donc inutile 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 que transmettre la valeur.

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

(Cela demande à EF de charger la chaîne de connexion nommée “MyEntities” à partir du fichier de configuration).

Je lance une exception personnalisée si ObjectContext est toujours nul. Je ne pense pas que ce sera le cas, mais c’est plus significatif que d’obtenir une NullReferenceException .

Je stocke le ObjectContext dans un champ afin de pouvoir 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 pour 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 doit régénérer la classe. Sinon, vous pouvez cliquer avec le bouton droit sur le fichier EDMX et sélectionner “Exécuter un 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 changé la classe de contexte de DbContext à CustomDbContext , Visual Studio vous donnera une erreur si vous essayez d’append une nouvelle classe de contrôleur MVC à l’aide du modèle «Contrôleur avec actions et vues lecture / écriture à l’aide de Entity Framework». Il dira “Type de contexte non pris en charge”. Pour contourner ce problème, ouvrez la classe “MyModel.Context.cs” générée et modifiez temporairement le type hérité dans DbContext . Après avoir ajouté votre nouveau contrôleur, vous pouvez revenir à CustomDbContext .

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

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

Je suis venu ici pour chercher un exemple de définition du délai d’attente pour une seule commande plutôt qu’un tel paramètre global.

Je pense que cela aidera probablement quelqu’un à avoir un exemple de ce que j’ai accompli:

 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();