简体   繁体   中英

One to Many LINQ query - Assembly does not have definition for SELECT

I am an experienced SQL Developer trying to learn LINQ. Say I have the following classes:

    public partial class Course
        {
            public Course()
            {
                this.Students = new HashSet<Student>();
                this.Students1 = new HashSet<Student>();
            }

            public int id { get; set; }
            public string name { get; set; }

            public virtual ICollection<Student> Students { get; set; }
            public virtual ICollection<Student> Students1 { get; set; }
        }

public partial class Student
    {
        public Student()
        {
            this.Courses = new HashSet<Course>();
        }

        public int id { get; set; }
        public string name { get; set; }
        public Nullable<int> age { get; set; }
        public Nullable<int> courseid { get; set; }

        public virtual Course Course { get; set; }
        public virtual ICollection<Course> Courses { get; set; }
    }

I am trying to get all the Students on the Computing course ie the student objects should be returned as a collection in the Course Object. I have tried this:

from c in Courses
.Include(s => s.Students)
.Where(c => c.name.StartsWith("Computing"))

select new {
c.name,
Students = c.Select(x => x.Students)

}

The error I get in LINQPAD is: Cannot execute text selection: 'Lib.Course' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'Lib.Course' could be found (press F4 to add a using directive or assembly reference)

Course is not an IEnumerable so it does not support Select method. As I see, you use LINQ query syntax (not method syntax as other solutions suggests), so you have to use this in your code:

from c in Courses
  .Include(s => s.Students)
  .Where(c => c.name.StartsWith("Computing"))

select new {
  c.name,
  c.Students
}

Simply write:

var res = Courses.Where(x => c.name.StartsWith("Computing"));

It will give you all courses (with students) that start with Computing

To be perfectly explicit:

var computerCourses = context.Students
   .Where(c => c.name.StartsWith("Computing"));
   .SelectMany(c => 
          c.Students.Select(s => new { CourseName = c.name, Student = s })
   .ToList();

This will give you a flat list of an anonymous type with fields 'CourseName' and 'Student', which is what I think you are after.

So the main problem with your query was the Select on the Course.Students collection: This collection which contains Student objects, which don't have a member 'Students' themselves - so you can't select that.

I would recommend coding these things in Visual Studio. Like this, your compiler will tell you exactly which statement is not correct, not only the line.

Also, in general I recommend using LINQ-Method-Chain over LINQ-Query syntax ('from' 'select' etc.) .. I find it is easier to think about the objects you're effectively dealing with. And it also helps me to keep apart SQL and LINQ syntax - they are quite similar, but work quite differently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM