views:

302

answers:

2

// From my form

BindingSource bs = new BindingSource();

private void fillStudentGrid()
{
     bs.DataSource = Admin.GetStudents();
     dgViewStudents.DataSource = bs;
}

// From the Admin class

public static List<Student> GetStudents()

{
    DojoDBDataContext conn = new DojoDBDataContext();

    var query =
        (from s in conn.Students
         select new Student
         {
             ID = s.ID,
             FirstName = s.FirstName,
             LastName = s.LastName,
             Belt = s.Belt
         }).ToList();

    return query;
}

I'm trying to fill a datagridview control in Winforms, and I only want a few of the values. The code compiles, but throws a runtime error:

Explicit construction of entity type 'DojoManagement.Student' in query is not allowed.

Is there a way to get it working in this manner?

+1  A: 

Just return a list of objects of an anonymous type :

public static List<object> GetStudents()
{
    DojoDBDataContext conn = new DojoDBDataContext();

    var query =
        (from s in conn.Students
         select new
         {
             ID = s.ID,
             FirstName = s.FirstName,
             LastName = s.LastName,
             Belt = s.Belt
         }).Cast<object>().ToList();

    return query;
}
Thomas Levesque
Great, that works! I can't help but to think there's a better way than casting though.
mdvaldosta
Well, you can't return a list of an anonymous type, an a `List<anonymous type>` can't be assigned to a list of objects... so you have to cast. Anyway, it would probably better to return real Student objects from GetStudents, and perform the projection only before you assign the datasource
Thomas Levesque
+4  A: 

You already have an IEnumerable<Student> instance and you cannot project entities from a query for the reasons described here)

You also don't need to create a list to bind to this data source - you can greatly simplify your method by changing it to this:

public static IEnumerable<Student> GetStudents()
{
    return new DojoDBDataContext().Students;
}

There is no reason to project a new instance to only map a few of the properties, by executing the query you are returning all the values anyhow and your projection doesn't save you anything. If you really want to only return a few values from this query for the purposes of information hiding you could do this:

public static IEnumerable<Object> GetStudents()
{
    DojoDBDataContext conn = new DojoDBDataContext();

    return conn.Students
               .Select(s => new {
                   ID = s.ID,
                   FirstName = s.FirstName,
                   LastName = s.LastName,
                   Belt = s.Belt 
               });
}

Edit: If you aren't using C# 4 you will have to cast the contents of the IEnumerable<T> to Object explicitly. Only C# 4 supports covariance for IEnumerable<T>. So if you are using C# 3 you will have to do this:

public static IEnumerable<Object> GetStudents()
{
    DojoDBDataContext conn = new DojoDBDataContext();

    return conn.Students
               .Select(s => new {
                   ID = s.ID,
                   FirstName = s.FirstName,
                   LastName = s.LastName,
                   Belt = s.Belt 
               }).Cast<Object>();
}
Andrew Hare
I'm projecting a new Student instance because... well I don't really know what I'm doing (obviously). I can get the all the info from all the students easily, but I only NEED a few of the fields and am filling the datagrid view at runtime as it's read only.
mdvaldosta
Thanks for the code, and the lesson.
mdvaldosta