11
votes

Linq paresseux est-il évalué?

Salutations, j'ai la question suivante. Je n'ai pas trouvé la réponse exacte pour cela, et c'est vraiment intéressant pour moi. Supposons que j'ai le code suivant qui récupère les enregistrements de la base de données (afin d'exporter le fichier XML, par exemple).

var result = from emps in dc.Employees
  where emps.age > 21
  select emps;

foreach (var emp in result) {
  // Append this record in suitable format to the end of XML file
}


0 commentaires

4 Réponses :


11
votes

Toutes les données seront extraites de SQL Server, à la fois et mises en mémoire. Le seul moyen de contourner cela que je peux penser, c'est de traiter des données dans des morceaux plus petits (comme une page comme saut () et prendre ()). Mais, bien sûr, cela nécessite plus de hits sur SQL Server.

Voici une méthode d'extension de paging LINQ que j'ai écrit pour faire ceci: p>

public static IEnumerable<TSource> Page<TSource>(this IEnumerable<TSource> source, int pageNumber, int pageSize)
    {
        return source.Skip((pageNumber - 1) * pageSize).Take(pageSize);
    }


2 commentaires

Je ne pense pas que plus le serveur SQL Server sera un problème de performance si important si nous définissons la taille de la page correctement. Cela devrait être d'environ 1000 lignes pour mon exemple, je pense, et lorsque l'application sera principalement occupée avec l'exportation, non pas avec la mise en page de la base de données.


@ Spirit_1984 - Je suis d'accord avec toi. Je préférerais beaucoup avoir plus de coups sur SQL Server que de tenter de charger des millions de lignes en mémoire.



5
votes

Oui, Linq utilise une évaluation paresseuse. La base de données serait interrogée lorsque le forach commence à exécuter, mais il faudrait aller toutes les données en une fois (il serait beaucoup moins efficace de faire des millions de requêtes pour un seul résultat à la fois).

Si vous craignez d'apporter trop de résultats en une seule fois, vous pouvez utiliser Skip and Top pour obtenir un nombre limité de résultats à la fois (accompagnez ainsi votre résultat).


0 commentaires

1
votes

Ce sera récupéré lorsque vous invoquez des méthodes tolistes ou similaires. LINQ a différé Exécution:

  • http: //weblogs.asp. Net / Psteele / Archive / 2008/04/18 / Linq-Deferred-Execution.aspx

    La voie - même avoir une exécution différée et charger toute la collection à partir d'une source de données dans le cas d'un ou de tout autre fournisseur LINQ - sera déterminé par l'implémenteur de la source d'objet LINQ.

    C'est, par exemple, certains ou / m peuvent fournir un chargement paresseux, ce qui signifie que votre "liste complète des clients" serait quelque chose comme un curseur et d'accéder à l'un des éléments (un employé), ainsi que d'une propriété, chargera l'employé lui-même ou la propriété accessible uniquement.

    Mais, de toute façon, ce sont les bases.

    EDIT: Maintenant, je vois que c'est une chose linq-to-SQL ... ou je ne sais pas si l'auteur de la question a mal compris Linq et il ne sait pas que Linq n'est pas linq-to-SQL, mais c'est plus un modèle et une caractéristique linguistique.


0 commentaires

0
votes

OK, maintenant grâce à ce Réponse J'ai une idée - comment À propos de mélanger la fonction de prendre une page avec Rendement de rendement forte> Possibilités? Voici l'échantillon du code:

// This is the original function that takes the page
public static IEnumerable<TSource> Page<TSource>(this IEnumerable<TSource> source, int pageNumber, int pageSize) {
  return source.Skip((pageNumber - 1) * pageSize).Take(pageSize);
}

// And here is the function with yield implementation
public static IEnumerable<TSource> Lazy<TSource>(this IEnumerable<TSource> source, int pageSize) {
  int pageNumber = 1;
  int count = 0;

  do {
    IEnumerable<TSource> coll = Page(source, pageNumber, pageSize);
    count = coll.Count();
    pageNumber++;
    yield return coll;
  } while (count > 0);
}


// And here goes our code for traversing collection with paging and foreach
var result = from emps in dc.Employees
  where emps.age > 21
  select emps;

// Let's use the 1000 page size
foreach (var emp in Lazy(result, 1000)) {
  // Append this record in suitable format to the end of XML file
}


0 commentaires