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.
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;
}
}
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 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;
}
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'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
.
Si cela peut aider, c'est le VB.Net solution:
Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout
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();