【问题标题】:display data form multiple tables in a strongly typed view在强类型视图中显示来自多个表的数据
【发布时间】:2012-11-13 18:22:45
【问题描述】:

我有一个强类型视图,它显示数据库表“Student_A”中的学生

查看:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Student.Models.Student_A>>" %>
    <table>
    <% foreach (var item in Model) { %>

        <tr>
            <td>
                <%= Html.Encode(item.StudentName) %>
            </td>
            <td>
                <%= Html.Encode(item.StudentId) %>
            </td>
        </tr>

    <% } %>

    </table>

控制器:

    public ActionResult ShowStudents()
    {
        ViewData.Model = stud.Student_A.Where(a => a.StudentId != 0);
        return View();
    }

我有另一个表“Student_B”也存储学生,我也想在我的视图中显示这个学生。比如:

    public ActionResult ShowAllStudents()
    {
        var StudentA = stud.Student_A.Where(a => a.StudentId != 0);
        var StudentB = stud.Student_B.Where(a => a.StudentId != 0);
        ViewData.Model = StudentA + StudentB;

        return View();
    }

是否可以在单个控制器操作中在强类型视图中显示来自两个不同表的数据?还是我必须创建一个数据库视图来显示“Student_A”和“Student_B”表中的学生,然后在视图中显示它们?

非常感谢任何帮助

【问题讨论】:

    标签: c# asp.net-mvc linq asp.net-mvc-4 razor


    【解决方案1】:

    您需要以“不可知”的方式存储结果。例如

    public class StudentInfo
    {
    public string Type { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ...
    }
    
    
    var students = stud.Student_A.Where(...).Select(a => new StudentInfo { Type = "Student_A", FirstName = a.FirstName, LastName = a.LastName });
    
    students.concat( stud.Student_B.Where(...).Select(b => new StudentInfo { Type = "Student_B", FirstName = b.FirstName, LastName = b.LastName });
    
    ViewData.Model = students;
    
    return View();
    

    通过这样做,您有一个通用的学生信息类来存储可以用作强类型模型的通用属性。

    或者,如果您想单独列出它们,您可以创建一个复合视图模型

    public class StudentsVM
    {
    public IEnumerable<Student_A> Student_A { get; set; }
    public IEnumerable<Student_B> Student_B { get; set; }
    }
    
    var vm = new StudentsVM;
    vm.Student_A = stud.Student_A.Where(...);
    vm.Student_B = stud.STudent_B.Where(...);
    
    ViewData.Model = vm;
    

    【讨论】:

    • 我的视图会继承什么? “对象”?
    • 使用第一种方法,如何在视图中显示结果?
    • 你的模特是IEnumerable&lt;StudentInfo&gt;
    • 这个列表包含多个学生,我会不会太循环模型项目来显示所有?如果我没有“IEnumerable”,它会给出错误。但是,当我添加“IEnumerable”时,我收到以下错误:编译器错误消息:CS0246:找不到类型或命名空间名称“StudentsViewModel”(您是否缺少 using 指令或程序集引用?)
    • StudentsViewModel 在什么命名空间中? IEnumerable&lt;Full.Namespace.Of.StudentsViewMode&gt; 或者,您可以在 web.config 中添加命名空间。有关当前自动导入的命名空间的列表,请参阅您的 web.config。但为了测试,我会先使用完整的命名空间。
    【解决方案2】:

    您可以同时创建视图模型

    public class StudentsViewModel
    {
      public List<Student.Models.Student_A> StudentsA {get;set}
      public List<Student.Models.Student_B> StudentsA {get;set}
    }
    

    如果 A 和 B 学生确实有不同的领域,请在您的视图中返回这个

    var viewModel = new StudentsViewModel();
    viewModel.StudentsA = stud.Student_A.Where(a => a.StudentId != 0);
    viewModel.StudentsB = stud.Student_B.Where(a => a.StudentId != 0);
    return View(viewModel);
    

    【讨论】:

    • Inherits="System.Web.Mvc.ViewPage
    • 此列表包含多个学生,因此必须循环遍历模型项目。如果我没有“IEnumerable”,它会给出错误。但是,当我添加“IEnumerable”时,出现以下错误:编译器错误消息:CS0246:找不到类型或命名空间名称“StudentsViewModel”(您是否缺少 using 指令或程序集引用?)
    【解决方案3】:

    我必须为 Treeview 而不是表做类似的事情,并且需要组合两个不同的集合以便从单个集合生成树视图。就我而言,我可以使用它来组合它们......

    var allStudents = StudentA.Union((IEnumerable<Object>)StudentB);
    

    然后在您的代码中,当您遍历集合中的每个对象时,您可以测试对象的数据类型并按照您的需要显示它,以防您想使用不同的代码来呈现不同类型的学生。我需要这样做,因为在我的情况下,具有子项的节点与没有子项的节点的类型完全不同。

    请注意,通过使用 Object 作为您的根集合类型而不是某种共享继承(例如接口),您将无法对组合集合进行排序或过滤它们。

    如果您需要混合这两个集合而不是将一个集合附加到另一个集合的末尾,则必须使用某种共享继承。

    更新

    示例代码表明这是可行的。我在LinqPad 中进行了测试,但我确信它在 Visual Studio 中也能正常工作。

    public class Student_A
    {
        public int Id{get;set;}
        public string FirstName{get;set;}
        public string LastName{get;set;}
    }
    
    public class Student_B
    {
        public int Id{get;set;}
        public string FirstName{get;set;}
        public string MiddleName{get;set;}
        public string LastName{get;set;}
    }
    
    void Main()
    {
        List<Student_A> StudentAs = new List<Student_A>();
        StudentAs.Add(new Student_A(){Id = 1, FirstName = "Jack", LastName = "Smith"});
        StudentAs.Add(new Student_A(){Id = 3, FirstName = "Sarah", LastName = "Jane"});
        StudentAs.Add(new Student_A(){Id = 7, FirstName = "Zack", LastName = "Hall"});
    
        List<Student_B> StudentBs = new List<Student_B>();
        StudentBs.Add(new Student_B(){Id = 2, FirstName = "Jane", MiddleName = "T.", LastName = "Kelly"});
        StudentBs.Add(new Student_B(){Id = 9, FirstName = "Rose", MiddleName = "Marie", LastName = "Tyler"});
        StudentBs.Add(new Student_B(){Id = 4, FirstName = "Bobby", MiddleName = "Stephen", LastName = "Singer"});
    
        var result = StudentAs.Union((IEnumerable<Object>)StudentBs);
    
        result.Dump();
    }
    

    【讨论】:

    • 不能以这种方式拥有强类型视图,对吗?在这种情况下,我的视图会继承什么?
    • 对于在顶部定义页面视图模型的实际行,您是对的@model IEnumerable&lt;object&gt;。但是,当您遍历对象集合时,如果您愿意,您可以将对象转换或寻址为它们的实际类型,以获得正确的智能感知。或者,您可以将具有集合的强类型视图模型作为单独的属性传递,并将它们组合在视图中以满足您的需要,以便在单个表中显示它们。如果我记得,这也是我最终在我的案例中所做的事情。
    • 尝试您建议的方法时出错:'System.collections.Generic.List 不包含'Union'的定义和最佳扩展方法重载'System .Linq.Queryable.Union(System.Linq.IQueryable, System.Collections.Generic.IEnumerable)' 有一些无效参数
    • 它是 System.Linq 中的扩展方法,您可能必须确保命名空间从您正在使用的页面解析。
    • 我刚刚检查了一下,它似乎对我来说工作正常,我的确切代码行的唯一区别是一些排序......这是我项目中的行,也许它会帮助你找出原因你的似乎给出了那个错误? (typeItem.Structures.OrderBy(x =&gt; x.Priority).ThenBy(x =&gt; x.DisplayName)).Union((IEnumerable&lt;Object&gt;)typeItem.Types.OrderBy(x =&gt; x.DisplayName))也许也将第一个集合转换为 IEnumerable
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    相关资源
    最近更新 更多