Je reçois des dépassements de délai en utilisant Entity Framework (EF) lorsque j'utilise une importation de fonction qui prend plus de 30 secondes. J'ai essayé ce qui suit et n'ai pas été en mesure de résoudre ce problème:
J'ai ajouté Default Command Timeout=300000
à la chaîne de connexion dans le fichier App.Config du projet contenant le fichier EDMX suggéré ici .
Voici à quoi ressemble ma chaîne de connexion:
<add
name="MyEntityConnectionString"
connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
res://*/MyEntities.msl;
provider=System.Data.SqlClient;provider connection string="
Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
MultipleActiveResultSets=True;Default Command Timeout=300000;""
providerName="System.Data.EntityClient" />
J'ai essayé de définir le CommandTimeout dans mon référentiel directement comme suit:
private TrekEntities context = new TrekEntities();
public IEnumerable<TrekMatches> GetKirksFriends()
{
this.context.CommandTimeout = 180;
return this.context.GetKirksFriends();
}
Que puis-je faire de plus pour obtenir le FE de l'expiration du délai? Cela ne se produit que pour de très grands ensembles de données. Tout fonctionne bien avec de petits ensembles de données.
Voici l'une des erreurs que je reçois:
System.Data.EntityCommandExecutionException: une erreur s'est produite lors de l'exécution de la définition de la commande. Voir l'exception interne pour plus de détails. ---> System.Data.SqlClient.SqlException: le délai a expiré. Le délai d'attente s'est écoulé avant la fin de l'opération ou le serveur ne répond pas.
OK - Je travaille et c'est idiot ce qui s'est passé. J'avais à la fois la chaîne de connexion avec Default Command Timeout=300000
et le CommandTimeout défini sur 180. Lorsque j'ai supprimé le Default Command Timeout
de la chaîne de connexion, cela a fonctionné. La solution consiste donc à définir manuellement CommandTimeout dans votre référentiel sur votre objet de contexte de la manière suivante:
this.context.CommandTimeout = 180;
Apparemment, définir les paramètres de délai d'attente dans la chaîne de connexion n'a aucun effet sur celle-ci.
Il existe un problème connu avec la spécification du délai d'expiration de la commande par défaut dans la chaîne de connexion EF.
http://bugs.mysql.com/bug.php?id=56806
Supprimez la valeur de la chaîne de connexion et définissez-la sur l'objet de contexte de données lui-même. Cela fonctionnera si vous supprimez la valeur en conflit de la chaîne de connexion.
this.context.Database.SetCommandTimeout(180);
this.context.Database.CommandTimeout = 180;
((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;
this.context.CommandTimeout = 180;
Si vous utilisez un DbContext, utilisez le constructeur suivant pour définir le délai d'expiration de la commande:
public class MyContext : DbContext
{
public MyContext ()
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 1 * 60; // value in seconds
}
}
Si vous utilisez DbContext
et EF v6 +, vous pouvez également utiliser:
this.context.Database.CommandTimeout = 180;
Habituellement, je gère mes opérations dans un transaction. Comme j'ai pu le constater, il n'est pas suffisant de définir le délai d'expiration de la commande de contexte, mais la transaction nécessite un constructeur doté d'un paramètre de délai d'expiration. Je devais définir les deux valeurs de délai d'attente pour que cela fonctionne correctement.
int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}
À la fin de la fonction, je ramène le délai d'attente de la commande à la valeur précédente de prevto.
Utiliser EF6
Si vous utilisez Entity Framework comme moi, vous devez définir Time out on Startup class comme suit:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));
Je sais que c'est un très vieux fil en cours d'exécution, mais EF n'a toujours pas résolu ce problème. Pour les personnes utilisant DbContext
généré automatiquement, vous pouvez utiliser le code suivant pour définir le délai d'attente manuellement.
public partial class SampleContext : DbContext
{
public SampleContext()
: base("name=SampleContext")
{
this.SetCommandTimeOut(180);
}
public void SetCommandTimeOut(int Timeout)
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
objectContext.CommandTimeout = Timeout;
}
C'est ce que j'ai financé. Cela aidera peut-être quelqu'un:
Alors on y va:
Si vous utilisez LINQ avec EF, recherchez certains éléments exacts contenus dans la liste, comme suit:
await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();
tout va bien jusqu'à ce que IdList contienne plus d'un identifiant.
Le problème de "délai d'attente" apparaît si la liste ne contient qu'un seul identifiant. Pour résoudre le problème, utilisez la condition if pour vérifier le nombre d'identifiants dans IdList.
Exemple:
if (IdList.Count == 1)
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();
}
else
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();
}
Explication:
Essayez simplement d'utiliser Sql Profiler et vérifiez l'instruction Select générée par Entity frameeork. …
Si vous utilisez DbContext et EF v6 +, vous pouvez utiliser la propriété CommandTimeout
this.context.Database.CommandTimeout = 180;