2012-04-13 3 views
9

Existe-t-il un moyen d'obtenir le nombre de lignes d'une requête Linq complexe et des millions d'enregistrements sans en tapant deux fois la db ou en écrivant 2 requêtes distinctes?C# Entity Framework Pagination

Je pourrais avoir ma propre suggestion. Ecrire une procédure stockée, mais je suis bon avec MySQL pas MSSQL.

Toutes les meilleures suggestions seraient géniales. En outre, si quelqu'un sait si Microsoft travaille sur l'ajout de cette fonctionnalité à l'infrastructure de l'entité.

+3

Je suis assez confiant que vous ne pouvez pas obtenir le nombre de lignes dans votre requête sans soit frapper la base de données ou écrire une requête distincte de celle qui retourne réellement ces lignes. –

+0

Merci @JonathanWood pour vos commentaires! –

+1

Lorsque vous utilisez .Count() dans EF, il ne sélectionne pas toutes les lignes, il n'exécute qu'une instruction sql select() from table' sql - alors que vous avez besoin de 2 requêtes, l'une d'elles est très bon marché. –

Répondre

2

La manière courante d'afficher des millions d'enregistrements est simplement de ne pas afficher toutes les pages. Pensez-y: si vous avez des millions d'enregistrements, disons 20 ou même 100 éléments par page, vous aurez des dizaines de milliers de pages. Cela n'a aucun sens de tout montrer. Vous pouvez simplement charger la page actuelle et fournir un lien vers la page suivante, c'est tout. Ou vous pouvez charger 100-500 enregistrements, mais toujours afficher une seule page et utiliser les informations d'enregistrements chargés pour générer des liens de page pour les premières pages (alors sachez avec certitude combien de pages sont disponibles).

+0

Vous avez raison, je ne voudrais pas montrer des centaines ou des milliers de liens ou même faire passer personne à travers ces nombreuses pages. Je suppose que le problème que j'ai est que je veux écrire une seule requête.Par exemple: MySQL vous a permis d'utiliser SQL_CALC_FOUND_ROWS dans une requête, puis une autre requête pour tirer juste ce résultat. Très efficace!!! Made Pagination merveilleux! Merci @VladimirPerevalov pour vos pensées! –

+0

AFAIK il n'y a pas un tel soutien dans LINQ ni dans MS SQL Server. En fait, il y a beaucoup de choses que MySQL fait et MS SQL ne fait pas. Par exemple. 'SELECT BETWEEN ...' est également très efficace pour la pagination. –

+0

vous pouvez également fournir une zone de texte "Aller à:" et un bouton pour accéder directement à une page spécifique. –

8

Je suggère d'utiliser la fonction Take(). Cela peut être utilisé pour spécifier le nombre d'enregistrements à prendre à partir d'une requête linq ou List. Par exemple

List<customers> _customers = (from a in db.customers select a).ToList(); 
var _dataToWebPage = _customers.Take(50); 

J'utilise une technique similaire dans une application MVC où je vous écris la liste des _Clients à la session, puis utiliser cette liste pour d'autres requêtes de pagination lorsque l'utilisateur clique sur la page 2, 3, etc. Cela permet d'économiser plusieurs hits de base de données. Cependant, si votre liste est très grande, l'écriture n'est pas une bonne idée.

Pour la pagination, vous pouvez utiliser les fonctions Skip() et Take() ensemble. Par exemple pour obtenir la page 2 des données:

var _dataToWebPage = _customers.Skip(50).Take(50); 
+0

Merci @TimNewton. Bien sûr, mais si j'ai un million d'enregistrements ou mieux encore un millier d'enregistrements avec de très grandes colonnes de données, vous rencontrez une exception de mémoire insuffisante. –

+0

Jason, vous pouvez écrire les clés primaires d'une liste dans la session plutôt que l'objet entier, puis extraire les détails de la base de données chaque fois que vous devez réafficher les données en utilisant les clés primaires de la liste? Cela nécessite néanmoins plusieurs lectures de base de données. Je ne pense pas que vous pouvez vous en sortir sans plusieurs lectures db si votre jeu de données est si grand. –

+0

vous pourriez avoir raison de ne pas être en mesure de faire une lecture db pour cette instance en C# et en utilisant Linq. Je sais que cela peut être fait, c'est juste que je veux la possibilité d'utiliser Linq pour qu'il soit fortement typé et va avec le reste de mon code propre. La pagination fonctionne parfaitement sur des tables plus petites qui ne contiennent pas de grands ensembles de données ou de grandes données. –

2

c'est si facile sur le serveur sql. vous pouvez écrire cette requête:

select count() over(), table.* from table 

le nombre() sur() retourne le nombre de ligne de total dans le résultat, vous n'avez pas besoin d'exécuter deux requêtes .. Rappelez-vous que vous devez exécuter raw sql sur votre contexte ou utilisez dapper qui renvoie le résultat en tant que modèle de vue