繁体   English   中英

序列不包含匹配元素

[英]Sequence contains no matching element

我有一个 asp.net 应用程序,我在其中使用 linq 进行数据操作。 运行时,我收到异常“序列不包含匹配元素”。

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

好吧,我希望是这一行抛出异常:

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

First()找不到任何匹配的元素,则会抛出异常。 鉴于您之后立即测试 null,听起来您想要FirstOrDefault() ,如果没有找到匹配的项目,它返回元素类型的默认值(对于引用类型为 null):

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

在某些情况下要考虑的其他选项是Single() (当您认为只有一个匹配元素时)和SingleOrDefault() (当您认为只有一个或零个匹配元素时)。 我怀疑FirstOrDefault是这种特殊情况下的最佳选择,但无论如何都值得了解其他人。

另一方面,看起来您首先加入这里实际上可能会更好。 如果您不关心它会进行所有匹配(而不仅仅是第一个),您可以使用:

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。

即使决定保持环路,我有几个建议:

  • 摆脱外部if 你不需要它,就好像 Count 为零一样,for 循环体永远不会执行
  • 在 for 循环中使用独占上限 - 它们在 C# 中更惯用:

     for (i = 0; i < _lstAcl.Documents.Count; i++)
  • 消除公共子表达式:

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

     foreach (var target in _lstAcl.Documents)

使用FirstOrDefault First 永远不会返回 null - 如果它找不到匹配的元素,它会抛出您看到的异常。

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

从 MSDN 库:

如果源不包含任何元素,则First<TSource>(IEnumerable<TSource>)方法将引发异常。 要在源序列为空时返回默认值,请使用FirstOrDefault方法。

对于在通过上下文菜单创建控制器时遇到此问题的人,以管理员身份重新打开 Visual Studio 修复了它。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM