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.
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;
}
}
Cela peut vous aider.
public class MyContext : DbContext
{
public MyContext () : base(ContextHelper.CreateConnection("my connection string"), 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 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;
}
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);
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.
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.
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.
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
.
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 à 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();