129 votes

La séquence ne contient aucun élément correspondant

J'ai une application asp.net dans laquelle j'utilise linq pour la manipulation des données. Lors de l'exécution, j'obtiens l'exception "Sequence contains no matching element".

if (_lstAcl.Documents.Count > 0)
{
    for (i = 0; i <= _lstAcl.Documents.Count - 1; i++)
    {
        string id = _lstAcl.Documents[i].ID.ToString();                           
        var documentRow = _dsACL.Documents.First(o => o.ID == id);
        if (documentRow !=null)
        {

            _lstAcl.Documents[i].Read = documentRow.Read;
            _lstAcl.Documents[i].ReadRule = documentRow.ReadRule;

            _lstAcl.Documents[i].Create= documentRow.Create;
            _lstAcl.Documents[i].CreateRule = documentRow.CreateRule;

            _lstAcl.Documents[i].Update = documentRow.Update;
            _lstAcl.Documents[i].UpdateRule = documentRow.UpdateRule;

            _lstAcl.Documents[i].Delete = documentRow.Delete;
            _lstAcl.Documents[i].DeleteRule = documentRow.DeleteRule;
        }
    }
}

244voto

Jon Skeet Points 692016

Je pense que c'est cette ligne qui déclenche l'exception :

var documentRow = _dsACL.Documents.First(o => o.ID == id)

First() lèvera une exception s'il ne trouve aucun élément correspondant. Étant donné que vous testez la nullité immédiatement après, il semble que vous vouliez que FirstOrDefault() qui renvoie la valeur par défaut du type d'élément (qui est nulle pour les types de référence) si aucun élément correspondant n'est trouvé :

var documentRow = _dsACL.Documents.FirstOrDefault(o => o.ID == id)

D'autres options à envisager dans certaines situations sont Single() (quand vous pensez qu'il y a exactement un élément correspondant) et SingleOrDefault() (lorsque vous pensez qu'il y a exactement un ou zéro élément correspondant). Je soupçonne que FirstOrDefault est la meilleure option dans ce cas particulier, mais il vaut quand même la peine de connaître les autres.

D'un autre côté, il semble que vous feriez mieux de vous inscrire ici dès le départ. Si vous ne vous souciez pas que cela fasse tous (et pas seulement la première) que vous pourriez utiliser :

var query = from target in _lstAcl.Documents
            join source in _dsAcl.Document
            where source.ID.ToString() equals target.ID
            select new { source, target };
foreach (var pair in query)
{
    target.Read = source.Read;
    target.ReadRule = source.ReadRule;
    // etc
}

C'est plus simple et plus efficace IMO.

Même si vous faire décider de garder la boucle, j'ai quelques suggestions :

  • Débarrassez-vous de l'extérieur if . Vous n'en avez pas besoin, car si Count est égal à zéro, le corps de la boucle for ne s'exécutera jamais.

  • Utilisez des limites supérieures exclusives dans les boucles for - elles sont plus idiomatiques en C# :

    for (i = 0; i < _lstAcl.Documents.Count; i++)
  • Éliminer les sous-expressions communes :

    var target = _lstAcl.Documents[i];
    // Now use target for the rest of the loop body
  • Dans la mesure du possible, utilisez foreach au lieu de for pour commencer :

    foreach (var target in _lstAcl.Documents)

42voto

Jakub Konecki Points 28852

Utilisez FirstOrDefault . First ne retournera jamais null - s'il ne trouve pas d'élément correspondant, il lève l'exception que vous voyez.

_dsACL.Documents.FirstOrDefault(o => o.ID == id);

19 votes

Juste pour clarifier légèrement - Premièrement pourrait renvoie null en général, si votre prédicat correspond à des valeurs nulles. Il ne peut simplement pas retourner null ici, car o.ID lèverait une NullReferenceException sur une valeur nulle.

11voto

KBoek Points 2150

De la bibliothèque MSDN : La méthode First(IEnumerable) lève une exception si la source ne contient aucun élément. Pour retourner à la place une valeur par défaut lorsque la séquence source est vide, utilisez la méthode FirstOrDefault

1voto

Ash Points 2825

Pour ceux d'entre vous qui ont rencontré ce problème lors de la création d'un contrôleur par le biais du menu contextuel, la réouverture de Visual Studio en tant qu'administrateur a permis de le résoudre.

-4voto

Elnaz Points 1579

Peut-être que l'utilisation de Where() avant First() peut vous aider, car mon problème a été résolu dans ce cas.

var documentRow = _dsACL.Documents.Where(o => o.ID == id).FirstOrDefault();

3 votes

Ce qui vous a aidé ici est l'utilisation de .FirstOrDefault() au lieu de .First() - l'utilisation de .Where(o => o.ID == id).FirstOrDefault() et .FirstOrDefault(o => o.ID == id) sera identique.

0 votes

@pwdst en utilisant la condition dans la clause Where et ensuite FirstOrDefault sans aucune expression lambda.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X