【问题标题】:Displaying Many-to-Many relationships (Nested ListViews?)显示多对多关系(嵌套列表视图?)
【发布时间】:2009-09-17 08:39:54
【问题描述】:

我很欣赏这可能是一个相当简单的问题 - 但我遇到了很多麻烦(作为一个初出茅庐的 ASP.NET 开发人员)。我从 SO 和 Google 获得了许多想法,但没有运气,我想我开始过度思考这一点,这似乎是一个标准场景,我相信我错过了一些明显的东西。

例如,我有三个标准示例表 - 请注意多对多关系。

Students
- student_id
- forename
- surname

Courses
- course_id
- course_name

StudentCourses
- studentcourse_id
- course_id
- student_id

我想在我的 ASP.NET 3.5 Web 应用程序上以类似于(最后一列是允许他们编辑学生信息的按钮)的方式显示这些:

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

“课程”列是学生当前注册的课程的列表。这可能是空的(尚未注册)或包含他们当前注册的课程的列表(逗号分隔或标准的无序 HTML 列表,我并不珍贵)。这不会是一个庞大的列表,因为学生在任何时候只能注册少数课程。

我尝试了许多解决方案,从 asp:Repeater 到我目前最喜欢的 3.5 附带的 ListView。我使用 LINQ to SQL 作为我的数据层(以防由于 LINQ 对多对多关系的复杂支持而很重要)。

【问题讨论】:

    标签: c# asp.net listview many-to-many


    【解决方案1】:

    您可以使用嵌套中继器。下面的示例调用代码隐藏文件中的辅助方法,该方法返回一个列表。您可以从中访问所有课程信息。我可以使用存储库类中的方法让它工作,所以使用下面的代码来解决这个问题:

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

    这里是完整的例子:

    <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>
    

    这可能不是最好的解决方案,但它是一个有效的解决方案,所以我希望它可以帮助你

    【讨论】:

    • 这似乎没问题,让我可以选择在子中继器中自定义 HTML,这很好。谢谢!
    【解决方案2】:

    很简单,您可以向“学生”类添加几个新属性,如下所示(在 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 );
        }  
    }
    

    现在您只需要一个中继器(绑定到学生集合),因为 Student 类的“CoursesDescription”属性消除了对子中继器的需求。

    顺便说一句,我强烈建议您以单数形式命名您的表格(即您以 1 行所代表的内容命名它们)。此外,从 StudentCourses 表中删除标识列并将其替换为跨 Student_Id 和 Course_Id 的复合键是一个强有力的案例。

    希望这会有所帮助。

    【讨论】:

    • 这是一个很棒的解决方案,我认为它非常适合我,因为我确实想在这种情况下使用逗号分隔的列表(尽管 - 这个解决方案对于 UL 和 LI 来说不会那么容易) (或者至少不那么优雅)?)。谢谢你的好回复! :)
    • 哦,旁白。我不太确定从表名中删除复数(尽管同意它们不应该出现在列名上)。不过,您可能对复合键是正确的 - 不需要。
    • 嗨,很高兴你喜欢我的建议。如果您需要一个列表(ul..li),那么您可以使用字符串生成器。如果可以的话,我倾向于避免在我的课程中添加 HTML 标记。
    • 这就是将列表传递给转发器的好处,它非常灵活。不过,上述解决方案似乎也是一个不错的选择。 +1
    • 您好,您可以粘贴实现的代码:CourseRepository.GetCoursesByStudentId(this.Student_Id)
    猜你喜欢
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多