序列不包含匹配的元素

我有一个asp.net应用程序,我正在使用linq进行数据操作。 在运行时,我得到了“序列不包含匹配元素”的exception。

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; } } } 

那么,我希望这是抛出exception的这条线:

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

如果找不到任何匹配的元素, First()将会抛出一个exception。 假设您之后立即testingnull,那么听起来就像您想要FirstOrDefault() ,如果找不到匹配的项目,它将返回元素types的默认值(对于引用types为null):

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

在某些情况下需要考虑的其他选项是Single() (当你相信只有一个匹配元素时)和SingleOrDefault() (当你相信只有一个或零个匹配元素时)。 我怀疑FirstOrDefault在这种情况下是最好的select,但是无论如何也值得了解。

另一方面,看起来你可能实际上最好join这里的join。 如果你不关心它会做所有匹配(而不是第一个),你可以使用:

 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 } 

IMO更简单更高效。

即使你决定保持循环,我有几个build议:

  • 摆脱外部if 。 你不需要它,就好像Count是零,for循环体永远不会执行
  • 在for循环中使用独占的上限 – 他们更习惯于C#:

     for (i = 0; i < _lstAcl.Documents.Count; i++) 
  • 消除常见的子expression式:

     var target = _lstAcl.Documents[i]; // Now use target for the rest of the loop body 
  • 在可能的情况下,使用foreach而不是从头开始:

     foreach (var target in _lstAcl.Documents) 

使用FirstOrDefault 。 首先不会返回null – 如果找不到匹配的元素,则会抛出exception。

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

从MSDN库: 如果源不包含元素,第一个(IEnumerable)方法将引发exception。 要在源序列为空时返回默认值,请使用FirstOrDefault方法

也许在First()之前使用Where()可以帮助你,因为在这种情况下我的问题已经解决了。

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