在MVC中返回一个列表会导致错误

时间:2014-03-24 08:57:03

标签: c# asp.net-mvc entity-framework asp.net-mvc-4

我正在尝试返回教育系统中的时间表列表。我的项目中有一个计划模型,其中包含以下属性:

public partial class Schedule
{
    public Schedule()
    {
        this.ClassTimes = new HashSet<ClassTime>();
        this.Scores = new HashSet<Score>();
    }

    public int Id { get; set; }
    public int TeacherId { get; set; }
    public int LessonId { get; set; }
    public int ClassId { get; set; }
    public int DegreeId { get; set; }
    public int FacultyId { get; set; }
    public int SemesterId { get; set; }
    public int MajorId { get; set; }
    public System.DateTime DateOfExame { get; set; }
    public string Capacity { get; set; }
    public string locationOfExame { get; set; }

    public virtual Class Class { get; set; }
    public virtual ICollection<ClassTime> ClassTimes { get; set; }
    public virtual Degree Degree { get; set; }
    public virtual Faculty Faculty { get; set; }
    public virtual Lesson Lesson { get; set; }
    public virtual Major Major { get; set; }
    public virtual ICollection<Score> Scores { get; set; }
    public virtual Semester Semester { get; set; }
    public virtual Teacher Teacher { get; set; }
}

所以在这个模型中我保存了我的实体的id,例如专业,老师,课程等。所以我需要返回我的日程表列表。所以我必须将我的实体的id转换为该实体的名称。所以我在我的MVC项目中设计了一个调度控制器,如下所示:

private readonly ScheduleRepositor obj = new ScheduleRepositor();

public ActionResult Index()
{
    var list=new List<SchedulePresentation>();
    ClassRepository objclassrep=new ClassRepository();
    DegreeRepositor objdegreerep=new DegreeRepositor();
    FacultyRepositor objfactulyrep=new FacultyRepositor();
    LessonRepository objLessonRep=new LessonRepository();
    MajorRepository objmajorrep=new MajorRepository();
    SemesterRepositor objsemesterrep=new SemesterRepositor();
    TeacherRepositor objteacherrep=new TeacherRepositor();
    DateConverter objdateconverte = new DateConverter();
    List<Schedule> model = obj.GetLessonlist();
    foreach (var t in model)
    {
       SchedulePresentation objpres=new SchedulePresentation();
        objpres.Capacity = t.Capacity;
        objpres.DateOfExam = objdateconverte.ConvertToPersianToShow(t.DateOfExame);
        objpres.className = objclassrep.FindClassById(t.ClassId).ClassName;
        objpres.degreeName = objdegreerep.FindDegreeById(t.DegreeId).DegreeName;
        objpres.examLocation = t.locationOfExame;
        objpres.facultyName = objfactulyrep.FindFacultyById(t.FacultyId).FacultyName;
        objpres.lessonName = objLessonRep.FindLessonById(t.LessonId).LessonName;
        objpres.majorName = objmajorrep.FindMajorById(t.MajorId).MajorName;
        objpres.semesterName = objsemesterrep.FindSemesterById(t.SemesterId).SemesterName;
        objpres.teacherName = objteacherrep.FindTeacherById(t.TeacherId).Name + " " +
                              objteacherrep.FindTeacherById(t.TeacherId).LastName;
        list.Add(objpres);

    }

    return View(list);
}

所以我只为每个实体创建一个存储库,通过 id 返回我的实体名称。

我为我的日程创建了一个表示类,将id转换为我的实体名称,如下所示:

public class SchedulePresentation
{
    public string teacherName { set; get; }
    public string lessonName { set; get; }
    public string className { set; get; }
    public string degreeName { set; get; }
    public string facultyName { set; get; }
    public string semesterName { set; get; }
    public string majorName { set; get; }
    public string DateOfExam { set; get; }
    public string Capacity { set; get; }
    public string examLocation { set; get; }
}

所以我有两个问题。我的解决方案中有4个项目:

  1. DomainClass
  2. 模型
  3. 存储库
  4. MVC项目
  5. 所以

    1. 我将这些Id转换为MVC层中的名称是一个好方法,还是最好为这个时间表列表创建一个Repository或创建一个模型?

    2. 在我想要返回列表的最后一行中,我收到了这个错误:

      传入字典的模型项的类型是&#39; System.Collections.Generic.List 1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable 1 [DomainClasses.Schedule]&#39;。

    3. MVC的视图代码:

      @model IEnumerable<DomainClasses.Schedule>
      
      @{
          ViewBag.Title = "Index";
      }
      
      <h2>Index</h2>
      
      <p>
          @Html.ActionLink("Create New", "Create")
      </p>
      <table>
          <tr>
              <th>
                  @Html.DisplayNameFor(model => model.TeacherId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.LessonId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.ClassId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.DegreeId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.FacultyId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.SemesterId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.MajorId)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.DateOfExame)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.Capacity)
              </th>
              <th>
                  @Html.DisplayNameFor(model => model.locationOfExame)
              </th>
              <th></th>
          </tr>
      
      @foreach (var item in Model) {
          <tr>
              <td>
                  @Html.DisplayFor(modelItem => item.TeacherId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.LessonId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.ClassId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.DegreeId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.FacultyId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.SemesterId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.MajorId)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.DateOfExame)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.Capacity)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.locationOfExame)
              </td>
              <td>
                  @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
                  @Html.ActionLink("Details", "Details", new { id=item.Id }) |
                  @Html.ActionLink("Delete", "Delete", new { id=item.Id })
              </td>
          </tr>
      }
      
      </table>
      

4 个答案:

答案 0 :(得分:2)

你的观点可能有像这样的强类型模型

@model IEnumerable<DomainClasses.Schedule>

但您要返回List<SchedulePresentation>

一种解决方案是将模型行更改为:@model IEnumerable<SchedulePresentation>

答案 1 :(得分:1)

您的问题的答案在于错误消息:

  

传递到字典中的模型项是类型的   &#39; {System.Collections.Generic.List {1}} 1 [DomainClasses.Schedule]&#39;

对应于此方法的视图(默认情况下,控制器的“索引”视图)似乎需要类型为1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable的模型。

如果您希望发送IEnumerable<Schedule>,请将视图中的模型类型更改为List<SchedulePresentation>

提示:在您看来,第一行之一应为以下形式:

IEnumerable<SchedulePresentation>

你可以这样改变:

@model IEnumerable<DomainClasses.Schedule>

答案 2 :(得分:1)

答案在于编译器报告的错误。当视图需要类型为SchedulePresentation的模型对象时,您将传递给某个类型的模型对象(Schedule)。

特别是,在行中:

List<Schedule> model = obj.GetLessonlist();
foreach (var t in model)
{
    SchedulePresentation objpres=new SchedulePresentation();
    objpres.Capacity = t.Capacity;
    objpres.DateOfExam = objdateconverte.ConvertToPersianToShow(t.DateOfExame);
    objpres.className = objclassrep.FindClassById(t.ClassId).ClassName;
    objpres.degreeName = objdegreerep.FindDegreeById(t.DegreeId).DegreeName;
    objpres.examLocation = t.locationOfExame;
    objpres.facultyName = objfactulyrep.FindFacultyById(t.FacultyId).FacultyName;
    objpres.lessonName = objLessonRep.FindLessonById(t.LessonId).LessonName;
    objpres.majorName = objmajorrep.FindMajorById(t.MajorId).MajorName;
    objpres.semesterName = objsemesterrep.FindSemesterById(t.SemesterId).SemesterName;
    objpres.teacherName = objteacherrep.FindTeacherById(t.TeacherId).Name + " " +
                                  objteacherrep.FindTeacherById(t.TeacherId).LastName;
    list.Add(objpres);
}

您正在创建List<Schedule>,但是当您在视图中指定的模型需要类型SchedulePresentation时,您会向其添加IEnumerable<DomainClasses.Schedule>类型的对象。因此,您有错误:

  

传递到字典中的模型项是类型的   'System.Collections.Generic.List 1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable 1 [DomainClasses.Schedule]'。

要解决此问题,请将模型行更改为@model IEnumerable<SchedulePresentation>

答案 3 :(得分:1)

关于你的第一个问题,我会说MVC控制器是从存储库返回的内容中提取信息的正确位置,并将其放在视图模型中(您的SchedulePresentation类)。但是,您发布的代码将导致大量数据库查询 - 对于计划中的每个项目,您最终将获得8个额外查询以获取相关项目。在包含20个项目的计划中,这是额外的160个数据库查询,以获取您可能包含的内容。

您已标记此[entity-framework],因此我假设您正在使用它来获取数据库中的Schedule项。而不是使用项目的id,使用实际属性:

for (var t in model) {
    SchedulePresentation objpres=new SchedulePresentation();
    objpres.Capacity = t.Capacity;
    objpres.DateOfExam = objdateconverte.ConvertToPersianToShow(t.DateOfExame);

    objpres.className = t.Class.ClassName; // <- this works!
}

现在,这样做不会为您节省任何数据库查询 - 它只会稍微清理您的代码。由于延迟加载,当您要求查看时,EF仍会从db 中检索相关的Class对象,而不是在顶部。但是,如果您在存储库中向EF查询添加Include语句,则将开始保存 - 然后EF将在原始查询中包含相关项,并且它们已经从数据库中获取。这看起来如下所示:

var ctx = getYourEFContextSomehow(); // pseudocode, obviously...

var scheduleItems = ctx.Schedules.Include(s => s.Class); 
// Add more Include for other objects

还有其他方法可以关闭特定属性或整个对象的延迟加载 - 请查看http://msdn.microsoft.com/en-us/data/jj574232