序列不包含匹配元素 [英] Sequence contains no matching element

查看:174
本文介绍了序列不包含匹配元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个asp.net应用程序,我正在使用linq进行数据操作。在运行时,我得到异常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;
}
}
}


解决方案

嗯,我希望这条线会抛出例外:

  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 =从_lstAcl.Documents中的目标
在_dsAcl.Document
中加入源其中source.ID.ToString()等于target.ID
select new {source,target} ;
foreach(查询中的var对)
{
target.Read = source.Read;
target.ReadRule = source.ReadRule;
// etc
}

这更简单,更有效的IMO。



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




  • 如果,则摆脱外部。您不需要它,就像Count为零,for循环体将永远不会执行

  • 在for循环中使用独占上限 - 它们在C#中更为惯用: / p>

      for(i = 0; i< _lstAcl.Documents.Count; i ++)


  • 消除常见的子表达式:

      var target = _lstAcl.Documents [i]; 
    //现在使用目标为其余的循环体


  • 使用 foreach 而不是开始:

      foreach(_lstAcl.Documents中的var target)



I have an asp.net application in which I am using linq for data manipulation. While running, I get the 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;
        }
    }
}

解决方案

Well, I'd expect it's this line that's throwing the exception:

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

First() will throw an exception if it can't find any matching elements. Given that you're testing for null immediately afterwards, it sounds like you want FirstOrDefault(), which returns the default value for the element type (which is null for reference types) if no matching items are found:

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

Other options to consider in some situations are Single() (when you believe there's exactly one matching element) and SingleOrDefault() (when you believe there's exactly one or zero matching elements). I suspect that FirstOrDefault is the best option in this particular case, but it's worth knowing about the others anyway.

On the other hand, it looks like you might actually be better off with a join here in the first place. If you didn't care that it would do all matches (rather than just the first) you could 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
}

That's simpler and more efficient IMO.

Even if you do decide to keep the loop, I have a couple of suggestions:

  • Get rid of the outer if. You don't need it, as if Count is zero the for loop body will never execute
  • Use exclusive upper bounds in for loops - they're 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
    

  • Where possible use foreach instead of for to start with:

    foreach (var target in _lstAcl.Documents)
    

这篇关于序列不包含匹配元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆