Reputation: 33
I have an existing stored procedure which when it gets called, populates a table with the weeks' football fixtures.
The user would then make their predictions for each fixture from drop downs and I then hope to insert all the predictions together using model binding.
I've shown the relevant code below from my view which is currently causing me a headache:
@model IEnumerable<PPLMVCNewOne.Models.sp_getMakeYourPredictions_Result>
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
@Html.DisplayFor(m => m.ElementAt(i).Home_Team)
What I'm trying to do is add an index so I can model bind within the action result.
It's at the html helper line that I'm getting the following error:
The result of a query cannot be enumerated more than once.
Can anyone please give me a pointer in the right direction?
Upvotes: 3
Views: 2163
Reputation: 565
I kept getting this error when I was getting back a list of items as an IEnumerable. I wanted to check manually if the correct information was coming back from the database, so, when I hit my breakpoint, I would examine the contents of the IEnumerable. Unbeknownst to me, until I read the answer, I was preventing it from being enumerated again just below, where it was getting processed.
Upvotes: 0
Reputation: 239430
You're using an IEnumerable
, which is fine, of course, but you need to understand what you're working with. Enumerations are great for things like for loops. They're optimized to be, obviously enough, be enumerated over, but the optimization means that you only get to do this once.
Since an enumeration doesn't really have a concept of "length of itself" (it's built to spit out an item until it's out of items, that's all). It can use Count
, but it has to calculate that, and the only way to calculate the total number of members to enumerate them and count them as they go by. That means you've just run the enumeration, so your for loop is left with nothing to use.
The way to get around this is to cast it to a different type, such as list, that doesn't have this problem. It's not quite as efficient as an enumberable, but you have no choice.
You can either do this using ToList()
and then save that to a var that you'll use for both the count and the for loop or just cast your model from the start using something like IList<>
or ICollection<>
instead of IEnumerable<>
.
Upvotes: 7
Reputation: 1538
Have the action return an IList instead of an IEnumerable by calling ToList().
Change the view to this
@model IList<PPLMVCNewOne.Models.sp_getMakeYourPredictions_Result>
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
@Html.DisplayFor(m => m.ElementAt(i).Home_Team)
...
Upvotes: 1