The sequence does not contain a matching element.

I have an asp.net application in which I use linq to process data. While working, I get the exception "The sequence does not contain the corresponding 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; } } } 
+80
c # exception linq
Oct 22 '10 at 6:11
source share
4 answers

Well, I would expect this line to throw an exception:

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

First() will throw an exception if it cannot find suitable elements. Given that you immediately check for a null value, it looks like you want FirstOrDefault() , which returns the default value for an element type (which is null for reference types) if no matching elements are found:

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

Other options to consider in some situations: Single() (when you think that there is only one matching element) and SingleOrDefault() (when you think that there is only one or zero matching element). I suspect that FirstOrDefault is the best option in this particular case, but he still knows about others.

On the other hand, it seems that in fact it may be more profitable for you to join you in the first place. If you didn’t care that it would make all matches (and not just the first ones), you can use:

 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 } 

This is a simpler and more effective IMO.

Even if you decide to keep the loop, I have a few suggestions:

  • Get rid of the external if . You do not need this, as if Count was zero, the body of the loop cycle will never execute
  • Use exclusive upper bounds for loops - they are more idiomatic in C #:

     for (i = 0; i < _lstAcl.Documents.Count; i++) 
  • Eliminate common subexpressions:

     var target = _lstAcl.Documents[i]; // Now use target for the rest of the loop body 
  • If possible, use foreach instead of for to start with:

     foreach (var target in _lstAcl.Documents) 
+160
Oct 22 '10 at 6:14
source share

Use FirstOrDefault . The first will never return null - if it cannot find the corresponding element, it throws an exception that you see.

 _dsACL.Documents.FirstOrDefault(o => o.ID == id); 
+25
Oct 22 '10 at 6:13
source share

from the MSDN library: the First (IEnumerable) method throws an exception if the source contains no elements. To return to the default value instead when the source sequence is empty, use the FirstOrDefault method

+9
Oct 22 '10 at 6:17
source share

Perhaps using Where () before First () may help you, as my problem was resolved in this case.

 var documentRow = _dsACL.Documents.Where(o => o.ID == id).FirstOrDefault(); 
-2
Aug 14 '16 at 8:03
source share



All Articles