简体   繁体   中英

How to combine multiple models into one using linq

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);

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();
}

4.Result: 在此处输入图片说明

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.

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