web-dev-qa-db-ja.com

シーケンスに一致する要素が含まれていません

データ操作にlinqを使用しているasp.netアプリケーションがあります。実行中に、「シーケンスに一致する要素が含まれていません」という例外が表示されます。

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

さて、例外をスローしているのは次の行だと思います:

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

First() は、一致する要素が見つからない場合に例外をスローします。すぐにヌルをテストしていることを考えると、 FirstOrDefault() のように聞こえます。一致するアイテムが見つからない場合、要素タイプのデフォルト値(参照タイプの場合はヌル)を返します。

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

いくつかの状況で考慮すべきその他のオプションは、 Single() (一致する要素が1つだけあると思われる場合)および SingleOrDefault() (一致する要素が1つまたは0あると思われる場合)です。この特定のケースではFirstOrDefaultが最適なオプションであると思われますが、とにかく他のものについて知る価値があります。

一方、実際には、ここで最初に結合を行う方が良いようです。 allマッチ(最初のマッチだけでなく)を行うことを気にしない場合は、以下を使用できます。

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
}

それは、より簡単なandより効率的なIMOです。

あなたがdoループを維持することに決めたとしても、私はいくつかの提案があります:

  • 外側の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)
    
197
Jon Skeet

FirstOrDefaultを使用します。最初にnullが返されることはありません。一致する要素が見つからない場合は、表示されている例外がスローされます。

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

mSDNライブラリから:ソースに要素が含まれていない場合、First(IEnumerable)メソッドは例外をスローします。ソースシーケンスが空のときにデフォルト値を返すには、FirstOrDefaultメソッドを使用します

10
KBoek

コンテキストメニューを使用してコントローラーを作成しているときにこの問題に直面した人のために、管理者としてVisual Studioを再度開いて修正しました。

0
Ash