2009-09-17 6 views
4

Je comprends que cette question peut être assez simple - mais j'ai pas mal de problèmes (en tant que développeur ASP.NET naissant). J'ai gagné un certain nombre d'idées de SO et de Google sans aucune chance et je pense que je commence à trop penser cela, il semble un tel scénario standard que je crois que je manque quelque chose d'évident.Afficher des relations plusieurs-à-plusieurs (ListViews imbriqués?)

J'ai par exemple, trois exemples de tables standard - notez la relation Many-to-Many.

Students 
- student_id 
- forename 
- surname 

Courses 
- course_id 
- course_name 

StudentCourses 
- studentcourse_id 
- course_id 
- student_id 

Je voudrais afficher ces derniers sur mon application Web ASP.NET 3.5 d'une manière qui ressemble à (la dernière colonne étant un bouton pour leur permettre de modifier les informations des étudiants):

Students: 
# Name   Courses     Actions 
1 Joe Bloggs Maths, English   [Manage] 
2 Arthur Sleep English     [Manage] 
3 Andy Mann  Maths, German, French [Manage] 

La colonne «cours» est une liste des cours auxquels l'étudiant est actuellement inscrit. Cela pourrait être vide (pas encore inscrit) ou contenir une liste (délimitée par des virgules ou une liste HTML standard non ordonnée, je ne suis pas précieux) de leurs cours actuellement inscrits. Ce ne serait pas une liste massive car un étudiant ne peut s'inscrire qu'à une poignée de cours à la fois.

J'ai essayé un certain nombre de solutions, allant d'asp: Repeater à mon favori actuel, le ListView qui est venu avec 3.5. J'utilise LINQ to SQL comme couche de données (au cas où c'est important en raison de la prise en charge compliquée de LINQ pour les relations many-to-many).

Répondre

2

Tout simplement, vous pouvez ajouter quelques nouvelles propriétés à votre classe « étudiant » comme suit (en C#):

public IEnumerable<Course> Courses 
{ 
    get { return CourseRepository.GetCoursesByStudentId(this.Student_Id); } 
} 

//Aggregate course names into a comma-separated list 
public string CoursesDescription 
{ 
    get 
    { 
     if (!Courses.Any()) 
      return "Not enrolled in any courses"; 

     return Courses.Aggregate(string.Empty, (currentOutput, c) => 
       (!String.IsNullOrEmpty(currentOutput)) ? 
       string.Format("{0}, {1}", currentOutput, c.Course_Name) : c.Course_Name); 
    } 
} 

Maintenant, quand vous aurez besoin d'un seul répéteur (lié à votre collection d'étudiants), car la nécessité du sous-répéteur est supprimée par la propriété "CoursesDescription" sur la classe Student. En outre, je recommande fortement de nommer vos tables au singulier (c'est-à-dire de les nommer après ce que représente une rangée). En outre, il existe de nombreux arguments pour supprimer la colonne d'identité de votre table StudentCourses et la remplacer par une clé composite sur Student_Id et Course_Id.

Espérons que cela aide.

+0

Ceci est une excellente solution, je pense que cela me convient bien car je veux utiliser une liste séparée par des virgules dans ce cas (bien que - cette solution ne fonctionnerait pas aussi facile pour UL & LI (ou du moins pas aussi élégamment)?). Merci pour la bonne réponse! :) – Amadiere

+0

Oh, les côtés.Je ne suis pas trop sûr de la suppression du pluriel des noms de table (bien que d'accord, ils ne devraient pas être sur les noms de colonnes). Cependant, vous avez probablement raison sur la clé composite - pas besoin de ça. – Amadiere

+0

Salut, heureux que vous aimez ma suggestion. Si vous avez besoin d'une liste (ul..li), vous pouvez utiliser un stringbuilder. J'ai tendance à éviter de mettre du code HTML dans mes cours si je peux l'aider. –

4

Vous pouvez utiliser des répéteurs imbriqués. L'exemple ci-dessous appelle une méthode secondaire dans le code derrière le fichier qui renvoie une liste. Vous pouvez accéder à toutes les informations sur les cours à partir de cela. Je pourrais le faire fonctionner avec une méthode d'une classe référentiel si utilisé le code ci-dessous pour contourner ce problème:

protected List<tblStudentCourses> GetStudentCoursesByStudentID(int id) 
{ 
return studentRepository.GetStudentCoursesByStudentID(id).ToList(); 
} 

Voici l'exemple complet:

<asp:Repeater ID="parentRepeater" runat="server" DataSourceID="myDataSource"> 
<HeaderTemplate>   
Header HTML   
</HeaderTemplate> 

<ItemTemplate> 

    <asp:Repeater ID="availabilityRepeater" runat="server" DataSource='<%#GetStudentCoursesByStudentID(Convert.ToInt32(Eval("studentCourseID"))) %>'> 
     <ItemTemplate> 
      <%# Eval("tblStudentCourses.courseName") %><br /> 
     </ItemTemplate> 
    </asp:Repeater> 

    Student Name example: <%#Eval("studentName")%> 

</ItemTemplate> 
<FooterTemplate> 
    Footer HTML 
</FooterTemplate> 

Ceci peut ne pas être la meilleure solution mais c'est une solution de travail s Oi espérons qu'il vous aide

+0

Cela semble être ok, me donne la possibilité d'être en mesure de personnaliser le code HTML dans le sous-répéteur qui est bon. Merci! – Amadiere