Sequenz enthält keine passenden Element


112

Ich habe eine asp.net-Anwendung, in der ich linq zur Datenmanipulation verwende. Während des Laufens erhalte ich die Ausnahme "Sequenz enthält kein passendes 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;
        }
    }
}

Antworten:


218

Nun, ich würde erwarten, dass es diese Zeile ist, die die Ausnahme auslöst:

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

First()löst eine Ausnahme aus, wenn keine passenden Elemente gefunden werden können. Da Sie unmittelbar danach auf null testen, klingt dies wie gewünscht. Dabei FirstOrDefault()wird der Standardwert für den Elementtyp (der für Referenztypen null ist) zurückgegeben, wenn keine übereinstimmenden Elemente gefunden werden:

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

Andere Optionen, die in einigen Situationen in Betracht gezogen werden müssen, sind Single()(wenn Sie glauben, dass es genau ein übereinstimmendes Element gibt) und SingleOrDefault()(wenn Sie glauben, dass es genau ein oder null übereinstimmende Elemente gibt). Ich vermute, dass FirstOrDefaultdies in diesem speziellen Fall die beste Option ist, aber es lohnt sich trotzdem, über die anderen Bescheid zu wissen.

Auf der anderen Seite sieht es so aus, als ob Sie mit einem Join hier überhaupt besser dran wären. Wenn es Ihnen egal wäre, dass alle Übereinstimmungen (und nicht nur die ersten) ausgeführt werden, können Sie Folgendes verwenden:

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
}

Das ist einfacher und effizienter IMO.

Auch wenn Sie sich entscheiden, die Schleife zu halten, habe ich einige Vorschläge:

  • Werde das Äußere los if. Sie brauchen es nicht, denn wenn Count Null ist, wird der for-Schleifenkörper niemals ausgeführt
  • Verwenden Sie exklusive Obergrenzen für for-Schleifen - sie sind in C # idiomatischer:

    for (i = 0; i < _lstAcl.Documents.Count; i++)
  • Beseitigen Sie häufige Unterausdrücke:

    var target = _lstAcl.Documents[i];
    // Now use target for the rest of the loop body
  • Verwenden Sie nach Möglichkeit foreachanstelle von for:

    foreach (var target in _lstAcl.Documents)

39

Verwenden Sie FirstOrDefault . First gibt niemals null zurück. Wenn kein passendes Element gefunden wird, wird die angezeigte Ausnahme ausgelöst.

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

19
Nur zur Verdeutlichung - First könnte im Allgemeinen null zurückgeben, wenn Ihr Prädikat mit null Werten übereinstimmt. Es kann hier einfach nicht null zurückgeben, da o.IDdies eine NullReferenceException auf einen Nullwert auslösen würde.
Jon Skeet

11

Aus der MSDN-Bibliothek:

Die First<TSource>(IEnumerable<TSource>)Methode löst eine Ausnahme aus, wenn die Quelle keine Elemente enthält. Verwenden Sie die FirstOrDefaultMethode , um stattdessen einen Standardwert zurückzugeben, wenn die Quellsequenz leer ist .


0

Für diejenigen unter Ihnen, die dieses Problem beim Erstellen eines Controllers über das Kontextmenü hatten, wurde es durch erneutes Öffnen von Visual Studio als Administrator behoben.


-4

Vielleicht kann es Ihnen helfen, Where () vor First () zu verwenden, da mein Problem in diesem Fall gelöst wurde.

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

3
Was Ihnen hier tatsächlich geholfen hat, ist die Verwendung von .FirstOrDefault () anstelle von .First () - die Verwendung von .Where (o => o.ID == id) .FirstOrDefault () und .FirstOrDefault (o => o.ID == id) ) wird identisch sein.
pwdst

@pwdst unter Verwendung der Bedingung in der Where-Klausel und dann FirstOrDefault ohne Lambda-Ausdruck.
Elnaz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.