2008-12-13 38 views
34

Satır numarasını linq sorgu sonuç kümesine nasıl yansıtabilirim. Bunun yerine söz sahibi birLinq Sorgu Sonuçlarına Satır Sayısı Nasıl Satılır

:

field1, alan2, alan3

alan 1, field2, alan3

isterim

:

1, alan 1, field2, alan3

2 alan1, alan2, alan3

İşte benim girişimim Şuna:

Maalesef
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count) 
{ 
    Guid guid = new Guid(gameId); 
    using (PPGEntities entities = new PPGEntities()) 
    { 
     int i = 1; 
     var query = from s in entities.Scores 
        where s.Game.Id == guid 
        orderby s.PlayerScore descending 
        select new ScoreWithRank() 
        { 
         Rank=i++, 
         PlayerName = s.PlayerName, 
         PlayerScore = s.PlayerScore 
        }; 
     return query.ToList<ScoreWithRank>(); 
    } 
} 

, "Sıralaması = i ++" satırı aşağıdaki derleme zamanı istisna atar:

+0

Olası kopyalar (http://stackoverflow.com/questions/269058/how-do-you-add-an-index-field- to-linq-results) –

cevap

55

Peki, en kolay "bir ifade ağaç bir atama operatörü içeremez"

public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count) 
{ 
    Guid guid = new Guid(gameId); 
    using (PPGEntities entities = new PPGEntities()) 
    { 
     var query = from s in entities.Scores 
        where s.Game.Id == guid 
        orderby s.PlayerScore descending 
        select new 
        { 
         PlayerName = s.PlayerName, 
         PlayerScore = s.PlayerScore 
        }; 

     return query.AsEnumerable() // Client-side from here on 
        .Select((player, index) => new ScoreWithRank() 
          { 
           PlayerName = player.PlayerName, 
           PlayerScore = player.PlayerScore, 
           Rank = index + 1; 
          }) 
        .ToList(); 

    } 
} 
+3

veritabanından her şeyi almak gerçekten bir 'çözüm' değildir. – Adaptabi

+1

@DotNetWise: Veritabanından * her şey almıyor - sadece sorguyla eşleşen bit. Veritabanından aynı miktarda veriyi orijinal denemeden alıyor - sadece biraz post-processing yapıyor. –

+0

Ne kadar? query.AsEnumerable() verilen gameId için tüm eşleşen kayıtları besleyecektir. Sadece 20'den sonra sıralanan pozisyonları almaya çalışın. Sıralamaya sahip olmak ve ihtiyacınız olan şeyi kesmek için her şeyi db'den alacaksınız. Gerçekten istenen çözüm değil! Bunun dışında - sayım parametresi nerede kullanılır? – Adaptabi

1

Tamam, hile yaptı: yönlü istemci tarafında ziyade veritabanı tarafında bunu ve aynı zamanda bir dizin sağlar Select aşırı kullanmak olacaktır. Teşekkürler.

İşte benim son kodu ...

Sunucu:

public List<Score> GetHighScores(string gameId, int count) 
{ 
    Guid guid = new Guid(gameId); 
    using (PPGEntities entities = new PPGEntities()) 
    { 
     var query = from s in entities.Scores 
        where s.Game.Id == guid 
        orderby s.PlayerScore descending 
        select s; 
     return query.ToList<Score>(); 
    }                  
} 

Müşteri

: Ayrıca orijinal koduna sadece hafif bir ayarlama yapabilir

void hsc_LoadHighScoreCompleted(object sender, GetHighScoreCompletedEventArgs e) 
{ 
    ObservableCollection<Score> list = e.Result; 

    _listBox.ItemsSource = list.Select((player, index) => new ScoreWithRank() 
          { 
           PlayerName = player.PlayerName, 
           PlayerScore = player.PlayerScore, 
           Rank = index+=1 
          }).ToList(); 
} 
+0

Gerçekten bir IEnumerable yerine bir Liste dönmek için GetHighScores() gerekir mi? Bunu bir listeye dönüştürecekseniz, sadece bir kez de yapabilirsiniz. –

+0

@Jon: Bunun yerine AsEnumerable'ı arayabilirdi ancak ... AsEnumerable yönteminin derleme zamanı kaynağını değiştirmek dışında bir etkisi yoktur. http://msdn.microsoft.com/en-us/library/bb335435.aspx - başka bir deyişle, nesneleri belleğe getirmeyecektir. Eğer kontrol etmek istiyorsa, ToList iyi –

+0

Evet, ama sadece * eğer * o noktada bunu yapmak gerekiyorsa. Tüm verileri iki kez kopyalamanın hiçbir anlamı kalmazsa. Bu yüzden benim cooment soru doğası :) Aslında AsEnumerable bile tabii ki gerekli değildir - GetHighScores yöntemi IEnumerable bunu yapmak için beyan edilir. –

0

Çalıştırmak için . Dikkatli bir şekilde, nesneye yeniden bağlanır veya nesneye erişirseniz, Rank her seferinde artar. Bu durumlarda en iyi cevap daha iyidir.

let Rank = i++ 

ve

Rank.ToString() 

Tam kodu:

public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count) 
{ 
Guid guid = new Guid(gameId); 
using (PPGEntities entities = new PPGEntities()) 
{ 
    int i = 1; 
    var query = from s in entities.Scores 
       let Rank = i++ 
       where s.Game.Id == guid 
       orderby s.PlayerScore descending 
       select new ScoreWithRank() 
       { 
        Rank.ToString(), 
        PlayerName = s.PlayerName, 
        PlayerScore = s.PlayerScore 
       }; 
    return query.ToList<ScoreWithRank>(); 
} 

}

+3

Bu kod bile derlenmeyecek. Bu, CS0832 hatasını üretir: Bir ifade ağacı, bir atama işleci –

0

Bu çözüm benim için çalıştı. http://www.dotnetfunda.com/articles/article1995-rownumber-simulation-in-linq.aspx

.Select((x, index) => new 
{ 
    SequentialNumber = index + 1 
    ,FieldFoo = x.FieldFoo       
}).ToList(); 
[nasıl Linq sonuçlarına bir indeks alanını eklerim] arasında
+0

içeremez Bir Int32 parametresini alan aşırı yük, varlık çerçevesi tarafından desteklenmez. DotNetFunda'daki makalenin, nesnelerle linq ile çalıştığına dikkat edin. –