2012-08-30 8 views
1

Je crée une page Web qui contient Posts et Comments. Lorsque je récupère le Comments pour chaque Post pendant le rendu de ce Post, cependant, la récupération est très lente. Je suppose que cela est dû à l'ouverture/fermeture des connexions fréquemment. Peu importe, ça ne va pas bien.Hiérarchie dans SQL et ASP.net

Pour résoudre ce problème, je considère fusionner les deux entités en une, et modéliser Posts et Comments de manière polymorphe. En d'autres termes, Entry devient une super-classe, sous-classée par Post et Comment.

Quelqu'un peut-il me dire si c'est une approche valide ou non? Alternativement, je suis ouvert à d'autres suggestions qui pourraient également résoudre le problème de performance imbriqué Repeater/DataList auquel je n'ai peut-être pas pensé.

+0

Si ma réponse vous a aidé, s'il vous plaît envisager de marquer comme « accepté » en cliquant sur la petite case à cocher sous son score. Si ce n'est pas le cas, faites-moi savoir quelles sont les informations dont vous avez besoin, afin que je puisse vous aider davantage. –

Répondre

1

Même si vous aviez un blog avec des milliers de commentaires sur le post, il fonctionnerait toujours bien.
Les tables RDBMS se trouvent souvent dans des millions d'enregistrements.

L'ouverture et la fermeture fréquentes des connexions constituent un goulot d'étranglement au niveau des performances.
Vous devriez aller chercher toutes les données à la fois, puis les transmettre à votre répéteur imbriqué.

1

Pour développer ce nunespascal dit:

Que vous tirez les données de retour comme deux entités distinctes par deux tables séparées OU vous tirant vers l'arrière polymorphically de la même table, il semble que la question vous avez environ comment vous demandez les données.

Tenir compte de ces deux approches en C# ish EF pseudo-code:

Approche 1: itérativement charge des enfants

var posts = db.Posts; 
foreach (Post p in posts) { 
    Html.Render(p); 

    var comments = db.Comments.Where(c => c.PostId == p.PostId); 
    foreach (Comment c in comments) { 
     Html.Render(c); 
    } 
} 

C'est ce que cela ressemble que vous faites essentiellement votre itération de répéteur actuelle. Pour chaque publication, chargez les commentaires qui lui appartiennent et restituez-les. Cela crée exactement le goulot d'étranglement que vous décriviez, dans lequel vous ouvrez/fermez beaucoup de connexions et exécutez beaucoup d'instructions SQL atomiques séparées. Évitez ceci si vous le pouvez.

Approche 2: Les parents de charge/enfants ensemble

var posts = db.Posts.Top(10); 
//^The .Top(10) limits the result-set to a manageable number of posts (10). 

var ids = posts.Select(p => p.PostId); 
//^This line creates an Enumerable list of the IDs of your loaded posts. 

var comments = db.Comments.Where(c => ids.Contains(c.PostId)); 
//^This line loads all the comments which belong to the 10 posts you loaded. 

foreach (Post p in posts) { 
    Html.Render(p); 

    foreach (Comment c in comments.Where(c => c.PostId == p.PostId)) { 
     // This loop iterates the comments in the same way the previous example 
     // showed, with the exception that it iterates *in memory*, rather than 
     // running additional SQL on each iteration. 
     Html.Render(c); 
    } 
} 

Parce que vous chargez tous les éléments en mémoire dans le second exemple, vous enregistrez tous les allers-retours - ne faisant que deux instructions SQL, tous les deux sont exécutés au début.

Si vous utilisez réellement EF4/5 (dont le code ci-dessus est basé sur), vous pouvez réellement même faire ce qui suit:

var posts = db.Posts.Include("Comments"); 
//^This line loads both Posts and Comments in a single SQL statement 

foreach (Post p in posts) { 
    Html.Render(p); 

    foreach (Comment c in p.Comments) { 
     // EF5 and other ORMs can create a .Comments property which contains an 
     // Enumerable list of the comments, already filtered on the FK binding 
     Html.Render(c); 
    } 
}