시퀀스에 일치하는 요소가 없습니다.


112

데이터 조작을 위해 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;
        }
    }
}

답변:


220

글쎄요, 예외를 던지는 줄은 다음과 같습니다.

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

First()일치하는 요소를 찾을 수 없으면 예외가 발생합니다. 나중에 null을 테스트한다는 점을 감안할 때 원하는 것처럼 들리며 FirstOrDefault()일치하는 항목이없는 경우 요소 유형의 기본값 (참조 유형의 경우 null)을 반환합니다.

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

일부 상황에서 고려해야 할 다른 옵션은 Single()(정확히 하나의 일치 요소가 SingleOrDefault()있다고 생각할 때 ) 및 ( 정확히 일치하는 요소 가 정확히 하나 또는 0이라고 생각할 때)입니다. 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가 0 인 것처럼 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)

39

FirstOrDefault를 사용하십시오 . 먼저 null을 반환하지 않습니다. 일치하는 요소를 찾을 수없는 경우보고있는 예외가 발생합니다.

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

19
간단히 설명하기 위해- 술어가 null 값과 일치하는 경우 First 일반적으로 null을 반환 할 수 있습니다. o.IDnull 값에 대해 NullReferenceException을 throw하는 것처럼 여기서 null을 반환 할 수 없습니다 .
Jon Skeet

11

MSDN 라이브러리에서 :

First<TSource>(IEnumerable<TSource>)소스 요소가없는 경우에있어서 예외가 발생. 소스 시퀀스가 ​​비어있을 때 대신 기본값을 반환하려면 FirstOrDefault메서드를 사용합니다 .


0

상황에 맞는 메뉴를 통해 컨트롤러를 만드는 동안이 문제에 직면 한 사용자를 위해 Visual Studio를 관리자로 다시 열면 문제가 해결되었습니다.


-4

이 경우 내 문제가 해결되었으므로 First () 전에 Where ()를 사용하면 도움이 될 수 있습니다.

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

3
여기서 실제로 도움이 된 것은 .First () 대신 .FirstOrDefault ()를 사용하는 것입니다-.Where (o => o.ID == id) .FirstOrDefault () 및 .FirstOrDefault (o => o.ID == id 사용 )는 동일합니다.
pwdst

@pwdst는 Where 절의 조건을 사용한 다음 람다 식없이 FirstOrDefault를 사용합니다.
Elnaz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.