mdarling mdarling - 1 month ago 19
ASP.NET (C#) Question

Add item to result set in asp.net mvc entity 5

I looked at some of the other questions here and could not find my answer. Maybe I am not searching with the right keywords.

public partial class CheckDirectReports_Result
{

[Key]
public Guid? id { get; set; }
public string NAME { get; set; }
public string EMPLID { get; set; }
public short EMPL_RCD { get; set; }
public bool hasSignedOff { get; set; }
}


So i have a stored procedure that runs and returns the results just fine. I then want to loop thru the results and compare the ID to see if it exists. If it does i want to add a bool flag to the record to display in the view.

var q = results.CheckDirectReports(EMPLID);


foreach (var i in q.ToList())
{
var g = results.PERSON_SIGN_OFF.Where(p => p.EMPLID == i.EMPLID).FirstOrDefault();
if(g != null)
{
i.hasSignedOff = true;
}
else
{
i.hasSignedOff = false;
}
}

return View(q);


I initially had it return like this before i put in the loop and everything worked fine

return View(q.AsEnumerable());


The problem is it tells me the result of a query cannot be enumerated more than once.

Here is my view:

@model IEnumerable<CodeOfConduct.Models.CheckDirectReports_Result>

<h2>Manager Sign Off</h2>


@using (Html.BeginForm("Save", "Manager", FormMethod.Post))
{

<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Employee ID</th>
<th></th>
<th>Select</th>
</tr>
</thead>
<tbody>
@foreach(var c in Model) // Print the list
{
<tr>

<td>@c.NAME</td>
<td>@c.EMPLID </td>

@{
if (c.hasSignedOff == true)
{
<td class="bg-success">Employee Has completed Sign-off</td>
}
else
{
<td class="bg-danger">Employee has not completed Sign-off</td>
}
}

<td>

@Html.ActionLink("Select Employee", "SignOff", new { ids=c.EMPLID, name = c.NAME })



</td>
</tr>
}
</tbody>

</table>


Why is it telling me the result of a query cannot be enumerated more than once?

Answer

you can return a List() to a View expecting an IEnumerable().

in your foreach, you enumerate the result q by doing q.ToList() just return q instead of q.AsEnumerable()

you can shorten your code using LINQ like this

    var q = results.CheckDirectReports(EMPLID).ToList();
    q.ForEach(a => {
        a.hasSignedOff = results.PERSON_SIGN_OFF.Any(p => p.EMPLID == a.EMPLID)
    });
    return View(q); 

if there are few records in the results.PERSON_SIGN_OFF i would select them all ToList() then check if the EMPLID exists to prevent multiple hits to the db.

    var q = results.CheckDirectReports(EMPLID).ToList();
    var signOffs = results.PERSON_SIGN_OFF.ToList();
    q.ForEach(a => {
        a.hasSignedOff = signOffs.Any(p => p.EMPLID == a.EMPLID)
    });
    return View(q); 

there might be an even better way to do this but we'd need to know more about your data structure