Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 显示多对多关系(嵌套列表视图?)_C#_Asp.net_Listview_Many To Many - Fatal编程技术网

C# 显示多对多关系(嵌套列表视图?)

C# 显示多对多关系(嵌套列表视图?),c#,asp.net,listview,many-to-many,C#,Asp.net,Listview,Many To Many,我明白这可能是一个相当简单的问题,但我有相当多的麻烦(作为一个羽翼未丰的ASP.NET开发人员)。我从SO和Google那里得到了很多想法,但运气不好,我想我开始想得太多了,这似乎是一个标准的场景,我相信我错过了一些明显的东西 例如,我有三个标准示例表——请注意多对多关系 Students - student_id - forename - surname Courses - course_id - course_name StudentCourses - studentcourse_id

我明白这可能是一个相当简单的问题,但我有相当多的麻烦(作为一个羽翼未丰的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应用程序上以类似的方式显示这些内容(最后一列是一个按钮,允许他们编辑学生信息):

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


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

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

protected List<tblStudentCourses> GetStudentCoursesByStudentID(int id)
{
return studentRepository.GetStudentCoursesByStudentID(id).ToList();
}
受保护列表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

学生姓名示例: 页脚HTML


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

非常简单,您可以向“Student”类添加几个新属性,如下所示(在C中):

公共IEnumerable课程
{
获取{return CourseRepository.GetCoursesByStudentId(this.Student_Id);}
}
//将课程名称聚合到逗号分隔的列表中
公共字符串课程描述
{
得到
{
如果(!Courses.Any())
返回“未参加任何课程”;
返回课程。聚合(string.Empty,(currentOutput,c)=>
(!String.IsNullOrEmpty(currentOutput))?
格式(“{0},{1}”,currentOutput,c.Course\u Name):c.Course\u Name);
}  
}
现在,您只需要一个中继器(绑定到您的学生集合),因为学生类上的“CoursesDescription”属性删除了对子中继器的需要

另一方面,我强烈建议您以单数命名表(即,以1行代表的内容命名)。此外,从StudentCourses表中删除identity列并用跨越Student_Id和Course_Id的复合键替换它也是一个很好的例子


希望这能有所帮助。

这是一个很好的解决方案,我认为它非常适合我,因为我确实希望在这种情况下使用逗号分隔的列表(尽管-对于UL&LI来说,这个解决方案不那么容易(或者至少不那么优雅)?)。谢谢你的回复!:)哦,旁白。我不太确定是否应该从表名中删除复数形式(尽管我同意它们不应该出现在列名上)。不过,关于复合键,你可能是对的,不需要。嗨,很高兴你喜欢我的建议。如果需要列表(ul..li),则可以使用stringbuilder。如果我能帮助的话,我倾向于避免在我的类中添加HTML标记。这是将列表传递给转发器的一件好事,它非常灵活。不过,上述解决方案似乎也是一个不错的选择+1您好,您是否可以粘贴实现以下功能的代码:CourseRepository.GetCoursesByStudentId(this.Student_Id)这似乎还可以,让我可以选择在子转发器中自定义HTML,这很好。谢谢
<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>
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 );
    }  
}