2009-04-05 6 views
3

J'utilise le code suivant pour interroger ma base de données:lignes en double lors de l'utilisation orderby, Skip() et Take() avec LINQ

private const int PAGE_SIZE = 10; 

public static IList<Image> GetTopImagesForUser(String connectionString, int userID, int page) 
{ 
    dbDataContext db = new dbDataContext(connectionString); 
    var images = (from p in db.Images 
        where (p.SubmitterUserIndex == userID && 
         p.URL != "none" && 
         p.ThumbURL != "none") 
        orderby p.Rep descending 
        select p).Skip(page * PAGE_SIZE).Take(PAGE_SIZE); 
    /* snip */ 
    return topImages; 
} 

Si j'appelle ce code avec une page de 0, tout fonctionne comme je le veux - je reçois une liste bien ordonnée, 10 résultats, tout est correct.

Si j'appelle ce code avec page de 1, cependant, les lignes qui étaient dans la page 0 finissent dans la page 1. Je ne peux même pas commencer à comprendre pourquoi. J'ai vérifié ma base de données pour les lignes en double, aucune. J'ai vérifié pour vous assurer que URL de chaque ligne et ThumbURL ne sont pas "aucun". Ce n'est pas le problème non plus. J'ai vérifié pour m'assurer que page est ce que je m'attends à ce que j'appelle quand j'appelle cette méthode, et c'est toujours ce que je m'attends à ce qu'il soit.

Ce qui me déconcerte est vraiment que la méthode suivante, qui diffère de la première méthode que dans le orderby clause, fonctionne complètement comme prévu.

public static IList<Image> GetAllImagesForUser(String connectionString, int userID, int page) 
{ 
    dbDataContext db = new dbDataContext(connectionString); 
    var images = (from p in db.Images 
        where (p.SubmitterUserIndex == userID && 
         p.URL != "none" && 
         p.ThumbURL != "none") 
        orderby p.SubmitTime descending 
        select p).Skip(page * PAGE_SIZE).Take(PAGE_SIZE); 
    /* snip */ 
    return allImages; 
} 

Est-ce que quelqu'un a rencontré quelque chose comme ça? Existe-t-il une autre forme que ma requête devrait prendre pour faire ce que je veux qu'elle fasse? Je ne suis pas sûr de ce que je pourrais manquer.

+0

C'est une bonne question. Lorsque vous rencontrez ce problème pour la première fois, c'est vraiment ahurissant. – DOK

+0

C'était ahurissant! C'est beaucoup plus logique maintenant! Merci :-) –

Répondre

8

Lorsque vous dites que vous n'avez pas de "lignes dupliquées", est-ce que l'une des lignes retournées a la même valeur Rep? Si c'est le cas, la commande à l'intérieur sera indéterminée.

Essayez

orderby p.Rep descending, p.SubmitTime 

(ou d'un autre ordre qui sera complètement déterminé) pour obtenir un résultat plus prévisible.

De plus, est-ce LINQ to SQL? Si c'est le cas, vous devriez regarder le SQL généré pour voir ce qui se passe.

+0

C'était exactement ça. Y compris SubmitTime a fait l'affaire. Wow, je ne l'aurais jamais deviné, mais maintenant que j'y pense, c'est logique que mon code original ne fonctionne pas. Merci! –

1

La colonne Rep que vous traitez dans le premier cas contient probablement des doublons. Lorsque vous sélectionnez le top 10 dans une liste contenant 100 lignes avec la valeur 1, il n'y a aucune garantie que les lignes seront retournées. Modifiez la clause order by pour inclure une colonne unique.

2

J'ai été déconcerté par des problèmes similaires dans la pagination lorsque vous n'utilisez pas LINQ, mais simplement en utilisant une requête SELECT (dans un sproc). Je pense que le problème peut être que le champ Rep n'est pas unique, mais le champ SubmitTime, étant une date, peut être unique.

Je suggérerais que vous essayiez un deuxième champ après Rep pour rendre l'ordre par toujours retourner les résultats dans le même ordre. Ce peut être n'importe quel champ qui rendra les enregistrements uniques; vous n'avez pas à l'utiliser dans les résultats.

Questions connexes