Reputation: 160
I have a SecurityLog Model returning rows from a sql database. I also have a SecurityLogOfficer and Officer table which contains many-many relationship.
How can I merge models together and display a concatenated list of officer names?
IQueryable<SecurityLog> sort = from s in _context.SecurityLog
.Include(f => f.SecurityLogOfficers)
.ThenInclude(e => e.Officer)
//.Select(x => new PageViewModel
//{ OfficersNames = string.Join(",", x.SecurityLogOfficers.Select(o => o.Officer.FullName)) })
select s;
Essentially I would like to take my list of SecurityLogOfficers and display list of officer names on one row (comma separated)
Update 02/11/20
@foreach (var item in Model.SecurityLog)
{
<tr>
<td style="width:4% !important">
@Html.DisplayFor(modelItem => item.ID)
</td>
<td style="width:5% !important">
@Html.DisplayFor(modelItem => item.EventDate)
</td>
<td style="width:5% !important">
@Model.OfficerNames[i]
}
Index Page Model
public class PageViewModel
{
public List<string> OfficerNames { get; internal set; }
}
This gives explicit conversion error....
IQueryable<SecurityLog> sort = from s in _context.SecurityLog
.Include(a => a.Entity)
.Include(b => b.EventType)
.Include(c => c.Location)
.Include(d => d.ShiftRange)
.Include(f => f.SecurityLogOfficers)
.ThenInclude(e => e.Officer)
.Select(x => new PageViewModel
{ OfficerNames = string.Join(",", x.SecurityLogOfficers.Select(o => o.Officer.FullName)) })
select s;
if (!String.IsNullOrEmpty(searchString))
{
sort = sort.Where(s => s.Narrative.Contains(searchString)
|| s.SubjectFirst.Contains(searchString)
|| s.SubjectLast.Contains(searchString)
|| s.OfficerNames.Contains(searchString));
}
SecurityLog = await PaginatedList<SecurityLog>.CreateAsync(sort
.Include(a => a.Entity)
.Include(b => b.EventType)
.Include(c => c.Location)
.Include(d => d.ShiftRange)
.Include(e => e.Officer)
.Include(f => f.SecurityLogOfficers)
.AsNoTracking(), pageIndex ?? 1, pageSize);
Upvotes: 0
Views: 1324
Reputation: 36645
Here is a working demo you could refer to:
1.Model:
public class SecurityLog
{
public int SecurityLogId { get; set; }
public string Name { get; set; }
public IList<SecurityLogOfficers> SecurityLogOfficers { get; set; }
}
public class Officer
{
public int OfficerId { get; set; }
public string Active { get; set; }
public string FullName { get; set; }
public IList<SecurityLogOfficers> SecurityLogOfficers { get; set; }
}
public class SecurityLogOfficers
{
public int OfficerId { get; set; }
public Officer Officer { get; set; }
public int SecurityLogId { get; set; }
public SecurityLog SecurityLog { get; set; }
}
2.Index.cshtml:
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.SecurityLog[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.SecurityLog[0].SecurityLogOfficers[0].Officer.FullName)
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.SecurityLog) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@(string.Join(",", item.SecurityLogOfficers.Select(u=>u.Officer.FullName)))
</td>
</tr>
}
</tbody>
</table>
3.Index.cshtml.cs:
public IList<SecurityLog> SecurityLog { get;set; }
public async Task OnGetAsync()
{
IQueryable<SecurityLog> sort = from s in _context.SecurityLog
.Include(f => f.SecurityLogOfficers)
.ThenInclude(e => e.Officer)
select s;
SecurityLog = await sort.ToListAsync();
}
Upvotes: 2
Reputation: 1171
You should use a display property the will do the concatenation or make the concatenation when mapping your db entity to your ViewModel (as commented line in your example). Given that it's probably for display purpose only, you shouldn't bring that logic at db level imo.
Upvotes: 1