Hi @anil kumar ,
It seems that you have post a duplicate thread: MVC Core with Linq, right?
I assume you have already got the attendance list with status, and now you want to convert the date list (or number list) from row to columns, like this:
convert
Name Number/Date Status
new 1 A
new 2 A
new 3 A
new 4 A
new 5 H
...
to
Name 1 2 3 4 5 ...
new A A A A H ...
If that is the case, you can refer to the following code, use group method to group the result by Name, then use a Dictionary to store the date/number and status.
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ApplicationDbContext _dbcontext;
public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
{
_logger = logger;
_dbcontext = context;
}
public IActionResult Index()
{
//first, we join the Employees and EmployeeAttendances table to get the employee name and the daily_date,
// then, in the select statement, we could query the employeeleave table and holiday table to set the status.
var queryresult = (from empatt in _dbcontext.EmployeeAttendances
join emp in _dbcontext.Employees
on empatt.Empid equals emp.Empid
select new EmployeeTemp()
{
Empid = emp.Empid,
Name = emp.Name,
Date = empatt.Daily_Date,
Status = (
empatt.Day == 1 ? "P" :
_dbcontext.EmployeeLeaves.Any(c => c.Empid == emp.Empid && empatt.Daily_Date >= c.StartDate && empatt.Daily_Date <= c.EndDate) ? "CL" :
_dbcontext.Holidays.Any(h => h.HolidayDate == empatt.Daily_Date) ? "H" :
empatt.Day == 0 ? "A" : "Unknown"
)
}).OrderBy(e=>e.Name).ThenBy(c=>c.Date).ToList();
//the queryresult as below:
// Emp1 2019/1/1 p
// Emp1 2019/1/2 P
// Emp1 2019/1/3 CL
//...
//Then, we could use the following code convert result to your required
var result = queryresult.GroupBy(c => c.Name).Select(g =>
{
var empvm = new EmployeeViewModel();
empvm.Name = g.Key;
empvm.Attendance = new Dictionary<DateTime, string>();
foreach (var i in g)
empvm.Attendance.Add(i.Date, i.Status);
return empvm;
}).ToList();
return View(result);
}
The EmployeeViewModel:
public class EmployeeViewModel
{
public string Name { get; set; }
public Dictionary<DateTime,string> Attendance { get; set; }
}
Finally, in the view page, we could use foreach
statement to loop through the dictionary and display the date and status.
@model IEnumerable<CoreMVC5.Models.EmployeeViewModel>
@{
ViewData["Title"] = "Index";
}
<table class="table table-bordered">
<thead>
<tr>
<th>
<label asp-for="@Model.FirstOrDefault().Name"></label>
</th>
@{
var firstdate = Convert.ToDateTime(Model.FirstOrDefault().Attendance.Keys.FirstOrDefault());
//base on the date to get the current month's days.
var days = DateTime.DaysInMonth(firstdate.Year, firstdate.Month);
}
@for (var numb = 1; numb <= days; numb++)
{
<th>@numb</th>
}
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
@for (var numb = 1; numb <= days; numb++)
{
//check whether the dictionary contains current day's data.
var selectdate = item.Attendance.AsEnumerable().Where(c => c.Key.Day == numb).FirstOrDefault();
if (selectdate.Key != DateTime.MinValue)
{
<td>@selectdate.Value</td>
}
else
{
<td></td>
}
}
</tr>
}
</tbody>
</table>
The result is below:
More detailed sample code, please refer MVC Core with Linq.
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Dillion