Vous avez en fait une élimination potentiellement prématurée, plutôt qu'une élimination tardive, car les entités impliquées dans la fermeture assignée à la source de données signifient qu'elle quitte la portée.
Vous avez alors avez une entité dans la nature qui ne sera pas éliminée dans sa portée réelle, ce dont se plaint l'analyse, mais cela ne devrait pas poser de problème par rapport au fait qu'elle est disposé avant sa dernière utilisation.
Options:
le laisser tel qu'il est. Si ce qui précède fonctionne, il est probablement car l'élimination n'affecte pas l'état nécessaire pour que la fermeture fonctionne. C'est risqué. Parier sur "probablement" n'est pas une bonne idée, et peut également changer sur la route. (Je peux penser à un cas où l'utilisation d'un objet après l'élimination est logique, mais c'est obscur et pas ce que vous avez ici de toute façon).
Forcer l'exécution de la requête avec impatience. L'appel ToList()
ou ToArray()
sur la requête l'exécutera et créera un résultat en mémoire qui est ensuite utilisé comme source de données. Au mieux, cependant, cela sera moins efficace dans l'espace et le temps. Au pire, il pourrait être paralysant (en fonction de la taille des résultats que vous avez affaire).
Assurez-vous que le contrôle se termine à l'aide de sa source de données avant de quitter l'étendue. Puis effacez la source de données. Selon le contrôle en question et d'autres questions (en particulier, s'il a une méthode explicite DataBind()
), il peut être trivial, impossible ou quelque part entre les deux.
Mettez l'entité dans une variable d'instance. Mettre en œuvre IDisposable
. Dans votre méthode Dispose()
, appelez sa méthode Dispose()
. N'ajoutez pas de finaliseur pour cela, car vous ne disposez que d'un objet géré.
Créez une méthode énumérable qui enveloppe la requête (et l'utilisation), puis exécute un yield return
sur chaque élément renvoyé par la requête. Utilisez ceci comme source de données.
5 semble le meilleur choix pour la plupart des cas. Il a l'avantage de ne pas modifier le code tout en ne rajoutant pas le préfixe (potentiellement grand, en fonction des données) du numéro 2. Notez qu'il suffit d'appeler AsEnumerable
(qui a presque le même effet sur l'ordre d'exécution) n'aurait pas le même effet, car la fermeture laisserait toujours le bloc non exécuté.
Edit: Une dénombrable qui enveloppe la requête serait comme:
private IEnumerable GetSessions()
{
using (var entities = new DbEntities(Properties.Settings.Default.UserConnectionString))
{
entities.CommandTimeout = 7200;
var sessions = from t in entities.TableName
where t.UserSession.Id == _id && t.Parent == 0
group t by new { t.UserSession, t.UserSession.SessionId } into sessionGroup
select new
{
Id = sessionGroup.Key.UserSession,
Session = sessionGroup.Key.SessionId
};
foreach(var sess in sessions.Where(x => x.Time > 0.00))
yield return sess;
}
}
Ensuite, vous définissez le changement SessionSummary_Load à:
private void SessionSummary_Load(object sender, EventArgs e)
{
summaryDataGridView.DataSource = GetSessions();
summaryDataGridView.Columns[4].DefaultCellStyle.Format = "N2";
summaryDataGridView.Columns[4].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
}
Espérons que cela va résoudre le problème, parce que entities
ne quitte jamais la portée du using
.
Cela ressemble à une bonne pratique, mais il ne s'est pas débarrassé de l'avertissement CA en ajoutant ToList(). Des idées? – esac
@esac: Je me demande si la réduction de la requête en une seule instruction ferait l'affaire? Essayez: 'var sessions = [/*...ce que vous avez ... * /] .Where (x => x.Time> 0.00) .ToList();' Et puis juste 'summaryDataGridView.DataSource = sessions;' Est-ce que ça marche? –
Non, mis à jour comme vous l'avez dit, et toujours obtenir la même erreur. – esac