Sıra eşleşen öğe içermiyor


113

Veri işleme için linq kullandığım bir asp.net uygulamam var. Çalışırken "Sıra eşleşen öğe içermiyor" istisnasını alıyorum.

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

Yanıtlar:


221

Şey, bu satırın istisnayı atmasını bekliyorum:

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

First()eşleşen herhangi bir öğe bulamazsa bir istisna atar. Hemen ardından null için test ettiğiniz göz önüne alındığında, istediğiniz gibi görünür FirstOrDefault()ve eşleşen öğe bulunmazsa öğe türü için varsayılan değeri (başvuru türleri için boştur) döndürür:

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

Bazı durumlarda göz önünde bulundurulması gereken diğer seçenekler Single()(tam olarak bir eşleşen öğe SingleOrDefault()olduğuna inandığınızda ) ve (tam olarak bir veya sıfır eşleşen öğe olduğuna inandığınızda). FirstOrDefaultBu özel durumda en iyi seçeneğin bu olduğundan şüpheleniyorum , ancak yine de diğerleri hakkında bilgi sahibi olmaya değer.

Öte yandan, ilk etapta burada bir katılımla daha iyi durumda olabileceğiniz görülüyor. Tüm eşleşmeleri yapmasını umursamadıysanız (sadece ilk maç yerine) şunu kullanabilirsiniz:

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
}

Bu daha basit ve daha verimli IMO.

Eğer bile yok döngü tutmaya karar, ben birkaç önerimiz var:

  • Dıştan kurtulun if. Buna ihtiyacınız yok, sanki Count sıfırmış gibi for döngüsü gövdesi asla çalışmayacak
  • Döngüler için özel üst sınırlar kullanın - bunlar C # 'da daha deyimseldir:

    for (i = 0; i < _lstAcl.Documents.Count; i++)
  • Yaygın alt ifadeleri ortadan kaldırın:

    var target = _lstAcl.Documents[i];
    // Now use target for the rest of the loop body
  • Mümkün olduğu durumlarda şununla başlamak foreachyerine kullanın for:

    foreach (var target in _lstAcl.Documents)

39

FirstOrDefault'u kullanın . Birincisi hiçbir zaman null döndürmez - eşleşen bir öğe bulamazsa, gördüğünüz istisnayı atar.

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

19
Sadece biraz açıklığa kavuşturmak için - Birinci olabilir senin yüklem boş değerler uyum olursa, genel olarak return null. o.IDBoş bir değere bir NullReferenceException atacağı gibi , burada da null döndüremez .
Jon Skeet

11

MSDN kitaplığından:

First<TSource>(IEnumerable<TSource>)Kaynak herhangi bir öğe içeren, bu yöntem bir durum oluşturur. Bunun yerine, kaynak dizisi boşken varsayılan bir değer döndürmek için FirstOrDefaultyöntemi kullanın .


0

Bağlam menüsü aracılığıyla bir denetleyici oluştururken bu sorunla karşılaşanlar için, Visual Studio'nun yönetici olarak yeniden açılması sorunu düzeltti.


-4

Sorunum bu durumda çözüldüğünden, First () 'den önce Where () kullanmak size yardımcı olabilir.

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

3
Burada size gerçekten yardımcı olan şey .First () yerine .FirstOrDefault () kullanmaktır - .Where (o => o.ID == id) .FirstOrDefault () ve .FirstOrDefault (o => o.ID == id) ) aynı olacaktır.
pwdst

@pwdst Where cümlesindeki koşulu kullanarak ve ardından herhangi bir lambda ifadesi olmadan FirstOrDefault.
Elnaz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.