سؤال

I'm trying to create an ASP.NET web service that exposes a list of students and courses with the Entity Framework. Each Course is composed of multiple Students:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Course
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<Student> Students { get; set; }
}

I am seeding the models like so:

protected override void Seed(StudentsContext context)
{
    var students = new List<Student> 
    {
        new Student { Id = 1, Name = "stu1" },
        new Student { Id = 2, Name = "stu2" },
        new Student { Id = 3, Name = "stu3" },
    };

    students.ForEach(s => context.Students.Add(s));
    context.SaveChanges();

    var courses = new List<Course> 
    {
        new Course { Id = 1, Title = "course1",
            Students = new List<Student>() { students[0], students[1] } },
        new Course { Id = 2, Title = "course2", 
            Students = new List<Student>() { students[0] } },         
        new Course { Id = 3, Title = "course3" },
    };

    courses.ForEach(c => context.Courses.Add(c));
    context.SaveChanges();
}

Visual Studio generated an ApiController for the Course with a GetCourses() method to get all the courses:

// GET api/Course
public IEnumerable<Course> GetCourses()
{
    return db.Courses.AsEnumerable();
}

However, when I use the web service to get the list of courses, it returns back JSON with courses that have students set to null:

[{"Id":1,"Title":"course1","Students":null},
 {"Id":2,"Title":"course2","Students":null},
 {"Id":3,"Title":"course3","Students":null}]

How could I get the web service to include the list of students that are assigned to each course? Thanks in advance.


UPDATE

Slauma's fix of changing GetCourses to

public IEnumerable<Course> GetCourses()
{
    return db.Courses.Include(c => c.Students).AsEnumerable();
}

partially worked. martin_costello's second solution had a similar effect. Something else I needed to do was to fix my Student class to clearly indicate the many-to-many relationship:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Course> CoursesAttending { get; set; }
}

public class Course
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<Student> Students { get; set; }
}
هل كانت مفيدة؟

المحلول

How could I get the web service to include the list of students that are assigned to each course?

You include by using Include:

public IEnumerable<Course> GetCourses()
{
    return db.Courses.Include(c => c.Students).AsEnumerable();
}

نصائح أخرى

I think the EntityFramework features for lazy loading may not be working because your collection property is not virtual. Also, you should call ToList() instead of AsEnumerable() so that the query materializes the objects from the database and executes the query before the method returns.

Otherwise the database context may be disposed and mean that the context (and database connection) no longer exist to do the look-up for the lazy loading to initialize the Students collection.

The AsEnumerable() call is effectively a no-op that is creating a query-plan to do an operation later when the results are actually needed (e.g. in a foreach loop). An ICollection<T> is already an IEnumerable<T>, so the cast would be unneccessary anyway.

The problem is that you aren't actually executing the query inside the GetCourses() method.

Try change the code to:

// GET api/Course
public IEnumerable<Course> GetCourses()
{
    return db.Courses.ToList();
}

But you may also need the Include() call as suggested in the other answer, in which case:

// GET api/Course
public IEnumerable<Course> GetCourses()
{
    return db.Courses.Include((p) => p.Students).ToList();
}

I had the same problem and it was solved by adding virtual modifier to model property

public virtual List<Service> Services { get; set; } 

I had same problem and this way resolved for me. Add below codes in WebApiCongif.cs file :

C# var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter);

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top