Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC/LINQ: What's the proper way to iterate through a Linq.EntitySet in a View?

OK so I have a strongly-typed Customer "Details" view that takes a Customer object Model.

I am using LINQ to SQL and every Customer can have multiple (parking) Spaces.

This is a FK relationship in the database so my LINQ-generated Customer model has a "Spaces" collection. Great!

Here is a code snippet from my CustomerRepository where I iterate through the Customer's parking spaces to delete all payments, spaces and then finally the customer:

public void Delete(Customer customer)
{
    foreach (Space s in customer.Spaces)
        db.Payments.DeleteAllOnSubmit(s.Payments);
    db.Spaces.DeleteAllOnSubmit(customer.Spaces);
    db.Customers.DeleteOnSubmit(customer);
}

Everything works as expected!

Now in my "Details" view I want to populate a table with the Customer's Spaces:

<% foreach (var s in Model.Spaces)
   { %>
    <tr>
        <td><%: s.ID %></td>
        <td><%: s.InstallDate %></td>
        <td><%: s.SpaceType %></td>
        <td><%: s.Meter %></td>
    </tr>
<% } %>

I get the following error:

foreach statement cannot operate on variables of type 'System.Data.Linq.EntitySet' because 'System.Data.Linq.EntitySet' does not contain a public definition for 'GetEnumerator'

Finally, if I add this bit of code to my Customer partial class and use the foreach in the view to iterate through ParkingSpaces everything works as expected:

public IEnumerable<Space> ParkingSpaces
{
    get
    {
        return Spaces.AsEnumerable();
    }
}

The problem here is that I don't want to repeat myself. I was also thinking that I could use a ViewModel to pass a Spaces collection to the View, however LINQ already infers and creates the Spaces property on the Customer model so I think it would be cleanest to just use that.

I am missing something simple or am I approaching this incorrectly?

Thanks!

like image 666
Jeff Camera Avatar asked Apr 25 '10 23:04

Jeff Camera


4 Answers

Sorry if Im a bit late answering this but the correct method of solving your problem is to add an assembly reference to your web.config file so that the view can access the GetEnumerator() method. You can do this using the assembly reference string provided in the page compliation error. eg

<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

like image 105
Alastair Hopkins Avatar answered Oct 20 '22 12:10

Alastair Hopkins


There are two ways you can do it, other than your little helper method.

You can inherit an IEnumerable of your class in the page:

<%@ Page Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Space>>" %>

<% foreach (var item in Model)
   {

Or you can cast your entity object to an IEnumerable:

<% foreach (var item in Model.Spaces as IEnumerable<Space>)
   {
like image 26
Robert Harvey Avatar answered Oct 20 '22 12:10

Robert Harvey


  • First of all using View Models instead of directly accessing DTOs is prefered. (use Automapper for this)

  • Second, Strongly type your views to View Model and in the View Model have an IEnumerable or List passed to the view, then you can iterate through it

like image 37
Mahesh Velaga Avatar answered Oct 20 '22 11:10

Mahesh Velaga


Just add a reference to System.Data.Linq to your project.

like image 31
Jeff Avatar answered Oct 20 '22 12:10

Jeff