2010-05-18 4 views

Répondre

6

Vous pouvez faire les deux. Il suffit d'exécuter le compte avant la prise. cela provoquera l'exécution de la requête deux fois, mais je crois que c'est inévitable. Si cela est dans un contexte Linq2SQL, comme votre commentaire l'indique, cela demandera en fait deux fois la base de données. En ce qui concerne le chargement paresseux, cela dépendra de la façon dont le résultat de la requête est réellement utilisé.

Par exemple: si vous avez deux tables et dire ProductProductVersion où chaque Product a plusieurs ProductVersions associés via une clé étrangère.

si ceci est votre requête:

var query = db.Products.Where(p => complicated condition).OrderBy(p => p.Name).ThenBy(...).Select(p => p); 

où vous suffit alors de sélectionner Products mais après l'exécution de la requête:

var results = query.ToList();//forces query execution 
results[0].ProductVersions;//<-- Lazy loading occurs 

si vous faites référence à une clé étrangère ou objet connexe qui ne faisait pas partie la requête d'origine sera alors chargée paresseuse. Dans votre cas, le compte ne provoquera pas de chargement paresseux car il renvoie simplement un int. mais en fonction de ce que vous faites réellement avec le résultat du Take() vous pouvez ou non avoir un chargement paresseux. Parfois, il peut être difficile de savoir si vous avez LazyLoading en cours, pour vérifier que vous devriez enregistrer vos requêtes en utilisant la propriété DataContext.Log.

+0

si vous utilisez le chargement différé, il exécute encore deux fois. Je ne suis toujours pas sûr de la manière exacte dont le chargement différé fonctionne. – Kieran

+0

@Kieran faites-vous linq2sql? ou linq à des objets ou autre chose? – luke

4

La meilleure façon serait de faire juste un Count de la requête, puis effectuez Take:

var q = ...; 
var count = q.Count(); 
var result = q.Take(...); 
2

Il est possible de le faire dans une seule requête Linq-to-SQL (où une seule instruction SQL sera exécutée). Le code SQL généré semble désagréable, donc vos performances peuvent varier.

Si ceci est votre requête:

IQueryable<Person> yourQuery = People 
    .Where(x => /* complicated query .. */); 

Vous pouvez ajouter ce qui suit à ce:

var result = yourQuery 
    .GroupBy (x => true) // This will match all of the rows from your query .. 
    .Select (g => new { 
     // .. so 'g', the group, will then contain all of the rows from your query. 
     CountAll = g.Count(), 
     TakeFive = g.Take(5), 
     // We could also query for a max value. 
     MaxAgeFromAll = g.Max(x => x.PersonAge) 
    }) 
    .FirstOrDefault(); 

Ce qui vous permettra d'accéder à vos données comme ceci:

// Check that result is not null before access. 
// If there are no records to find, then 'result' will return null (because of the grouping) 
if(result != null) { 

    var count = result.CountAll; 

    var firstFiveRows = result.TakeFive; 

    var maxPersonAge = result.MaxAgeFromAll; 

} 
Questions connexes