简体   繁体   中英

MVC Entity Framework using a nested foreach in view

I'm passing 3 sets of data through to a view in a viewmodel and have a problem relating one of them to the other two in my foreach coding:

My DB tables are: "ServiceGroups" is parent to "Services" "Services" is related through a joining table (using a 2 composite Primary Key) to the aspnet_users table (I call "Users")

I pulled this into an EF model called GWServices.edmx

so now I have 3 entities related like so: ServiceGroup (parent to) Service Service (many to many with) User

Then I created a controller and a viewmodel like this:

{

    public class ServicesViewModel
    {
        public ServicesViewModel(List<ServiceGroup> servicegroups, List<Service> services, List<User> aspnetusers)
        {
            this.ServiceGroups = servicegroups;
            this.Service = services;
            this.AspnetUsers = aspnetusers;

        }

        public List<ServiceGroup> ServiceGroups { get; set; }
        public List<Service> Service { get; set; }
        public List<User> AspnetUsers { get; set; }

    }


    public class ClientServicesController : Controller
    {

        public ActionResult Index()
        {
            GWEntities _db = new GWEntities();

            var servicegroups = _db.ServiceGroupSet.ToList();
            var services = _db.ServiceSet.ToList();
            var aspnetusers = _db.UserSet.ToList();

            return View(new ServicesViewModel(servicegroups, services, aspnetusers));
        }

    }
}

Next I created the view with 3 foreach loops to:

  1. Get and present as a UL, a list of all service groups in the database (which worked)
  2. Populate a table under each Servicegroup filling down some Service data for each Service within that given group (which also work)
  3. Test whether the user is associated with this particular Service, if so show only the red cross icon, otherwise show the green "select me" icon. (this doesn't populate any users)

So the code looks like this:

<% foreach (var servgroup in Model.ServiceGroups) { %> 
<ul> <%= servgroup.ServiceGroupName%> </ul>
<table>
     <% foreach (var serv in servgroup.Service)
        { %>
     <tr>
     <td class="td1">
     <%= serv.ServiceDescription%>
     </td>
     <td class="td2">
     <% = Html.Encode(String.Format("{0:f}",serv.MonthlyPrice)) %> 
        </td>
        <td class="td3"> 
           <%foreach (var user in serv.User) {%>
              <%if (user.UserName == User.Identity.Name)
                { %>
            <img src="/Content/LightRedCross_2.png" alt="" height="15px" width="15px"/>
                    <% }
                else
                {%>
            <img src="/Content/LightGreenAdd_2.png" alt="" height="15px" width="15px"/>           
              <%} %>
           <%} %>
        </td>
        </tr>
   <% } %> 
    </table> 
<% } %>

Can anyone tell me why foreach(var user in serv.user) does not recognise that "Customer1" (the currently logged in user) has 6 services ordered (as it is in the joining table)?

Thanks!

Paul

Looking at your code I think this could be resolved by loading the child tables of ServiceGroups.

It is likely that the Services & User reference was not loaded in the original Entity Framework query. Therefore, as you are trying to iterate through the children in the foreach loop, it does not see a collection, it just sees null.

You should try altering your retrieval statements:

_db.ServiceGroupSet.ToList()

to

_db.ServiceGroupSet.Include("ServiceSet").Include("UserSet").ToList()

If this doesn't fix your issue, I would put a break point on the below line of code and traverse the List to see if it has the data you expect.

this.ServiceGroups = servicegroups; 

For starters, username comparisons are generally case-insensitive. So this:

          <%if (user.UserName == User.Identity.Name)

...should be:

          <%if (user.UserName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))

You also have a bug where you don't dispose your entity context. You should override Controller.Dispose and dispose it there. This allows the view to render before the context is disposed.

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