Reputation: 7299
I am trying to return a list of schedule in education system. I have a schedule model in my Project with this property:
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; }
}
So in this model I save the id
of my entity for example major, teacher, lesson, etc. So I need to return a list of my schedules. So I have to convert the id
of my entity to name of that entity. So I design a schedule controller in my MVC project like this:
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);
}
So I just create a repository for each entity to return the name of my entity by id.
And I create a representation class for my schedule to convert the id
to name of my entities like this:
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; }
}
So I have two problems. I have 4 projects in my solution:
So
Is it a good method that I convert these Id to their name in the MVC layer, or it is better to make a Repository or create a model for this list of schedules?
In the last line when I want to return my list I got this error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable
1[DomainClasses.Schedule]'.
The view code of 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>
Upvotes: 1
Views: 411
Reputation: 60674
Regarding your first question, I'd say the MVC controller is the right place to extract the information from what the repository returns, and put it in a view model (your SchedulePresentation
class). However, the code you posted will result in an aweful lot of database queries - for each item in your schedule, you'll end up with eight extra queries to get the related items. In a schedule with 20 items, that's an extra 160 database queries to get stuff you could probably have included.
You've tagged this [entity-framework]
, so I'm going to assume that you're using it to get the Schedule
items from your database. Instead of using the id's of the items, use the actual properties:
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!
}
Now, doing just that will not save you any db queries - it will just clean up your code a little. Due to lazy loading, EF will still retrieve the relevant Class
object from the db when you ask to look at it, rather than at the top. However, if you in your repository add an Include
statement to your EF query, you'll start saving - then EF will include the related items in the original query, and they will already be fetched from the db. This will look something like the following:
var ctx = getYourEFContextSomehow(); // pseudocode, obviously...
var scheduleItems = ctx.Schedules.Include(s => s.Class);
// Add more Include for other objects
There are other ways to turn off lazy loading for specific properties or entire objects as well - check out http://msdn.microsoft.com/en-us/data/jj574232
Upvotes: 1
Reputation: 8227
The answer lies in the error reported by the compiler. You're passing to a view a model object of a certain type (SchedulePresentation
), when the view expects a model object of type Schedule
.
In particular, in the lines:
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);
}
you're creating a List<Schedule>
but you add to it objects of type SchedulePresentation
, when the model specified in your view expects the type IEnumerable<DomainClasses.Schedule>
. For this reason, you have the error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List
1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable
1[DomainClasses.Schedule]'.
To solve the problem, change your model line to @model IEnumerable<SchedulePresentation>
.
Upvotes: 1
Reputation: 23945
Your view probably has a strongly typed model like this
@model IEnumerable<DomainClasses.Schedule>
but you are returning a List<SchedulePresentation>
.
One solution would be to change the model line to: @model IEnumerable<SchedulePresentation>
.
Upvotes: 2
Reputation: 2656
The answer to your question lies in the error message:
The model item passed into the dictionary is of type 'System.Collections.Generic.List
1[EducationMVC.PresentationClass.SchedulePresentation]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable
1[DomainClasses.Schedule]'.
It seems like the view corresponding to this method (by default the Index view of your controller) is expecting a model of type IEnumerable<Schedule>
.
If you wish to send a List<SchedulePresentation>
, change the model type in the view to IEnumerable<SchedulePresentation>
.
Hint: In your view, one of the first lines should be of the form:
@model IEnumerable<DomainClasses.Schedule>
which you could change like this:
@model IEnumerable<EducationMVC.PresentationClass.SchedulePresentation>
Upvotes: 1