如何在另一个模型的页面模型中显示一个模型的串联列表?

时间:2020-01-21 14:28:20

标签: c# sql asp.net-core razor-pages

在我的主索引页面中,我想在“人员姓名”列中显示人员列表。即Tommy Bahamas,Clinton K等...

我遇到了麻烦,因为在索引页上,“官员”和“ SecurityLogOfficer”表不是我的SecurityLog模型的一部分。

SecurityLog索引页

@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">
            @Html.DisplayFor(modelItem => item.OfficerList)
        </td>
}

我创建了一个名为OfficerList的类,以返回以逗号分隔的Officer列表,但是我无法在SecurityLog索引页面上显示此列表。

public class OfficerList : SecurityLog
{
    private readonly SecurityCore.Models.SecurityCoreContext _context;

    public OfficerList(SecurityCore.Models.SecurityCoreContext context)
    {
        _context = context;
    }

    public List<string> GetOfficerList()
    {
        List<string> OfficerIDs = new List<string>();

        //use the syntax .ToList() to convert object read from db to list to avoid being re-read again
        var SecLog = _context.SecurityLog.ToList();
        var SecLogOfficer = _context.SecurityLogOfficer.ToList();
        var Officer = _context.Officer.ToList();


        int rowID;

        //string[] OfficerIDs = new string[100];
        rowID = 0;

        foreach (SecurityLog sl in SecLog)
        {
            foreach (SecurityLogOfficer slo in SecLogOfficer.Where(slo => slo.SecurityLogID == sl.ID))
            {
                if (OfficerIDs[rowID] == null)
                {
                    OfficerIDs[rowID] = slo.Officer.FullName + ", ";
                }
                else
                {
                    OfficerIDs[rowID] = OfficerIDs[rowID] + slo.Officer.FullName + ", ";
                }
            }

            rowID++;
        }

        return OfficerIDs;

    }

} 

这是我要显示串联列表的地方...

enter image description here

这是我的数据库架构和示例结果

Sql Database Schema

任何帮助将不胜感激。谢谢!

更新

我在检索SecurityLog模型中的串联名称列表时遇到问题。

public class SecurityLog
{
    private readonly SecurityCore.Models.SecurityCoreContext _context;

    public SecurityLog(SecurityCore.Models.SecurityCoreContext context)
    {
        _context = context;
    }

   ......

    public List<string> OfficerList
    {            
        get
        {                                
            var officerList = new OfficerList(_context);                

            return officerList.GetOfficerList();
        }
    }


 }

修改后的OfficerList类

public class OfficerList : SecurityLog
{
private readonly SecurityCore.Models.SecurityCoreContext _context;

public OfficerList(SecurityCoreContext context) : base(context)
{
    _context = context;
}

public List<string> GetOfficerList()
{
    List<string> OfficerIDs = new List<string>();

    //use the syntax .ToList() to convert object read from db to list to avoid being re-read again
    var SecLog = _context.SecurityLog.ToList();
    var SecLogOfficer = _context.SecurityLogOfficer.ToList();
    var Officer = _context.Officer.ToList();


    int rowID;

    //string[] OfficerIDs = new string[100];
    rowID = 0;

    foreach (SecurityLog sl in SecLog)
    {
        foreach (SecurityLogOfficer slo in SecLogOfficer.Where(slo => slo.SecurityLogID == sl.ID))
        {
            if (OfficerIDs[rowID] == null)
            {
                OfficerIDs[rowID] = slo.Officer.FullName + ", ";
            }
            else
            {
                OfficerIDs[rowID] = OfficerIDs[rowID] + slo.Officer.FullName + ", ";
            }
        }

        rowID++;
    }

    return OfficerIDs;

}

}

我对SecurityLog的_context表示它为空。

SqlNullValueException:数据为Null。此方法或属性不能为 调用Null值。 Microsoft.Data.SqlClient.SqlBuffer.ThrowIfNull() Microsoft.Data.SqlClient.SqlBuffer.get_DateTime() Microsoft.Data.SqlClient.SqlDataReader.GetDateTime(int i) lambda_method(Closure,QueryContext,DbDataReader,ResultContext, int [],ResultCoordinator) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable + Enumerator.MoveNext() System.Collections.Generic.List..ctor(IEnumerable集合) System.Linq.Enumerable.ToList(IEnumerable源) OfficerList.cs中的SecurityCore.Models.OfficerList.GetOfficerList() + var SecLog = _context.SecurityLog.ToList(); SecurityLog.cs中的SecurityCore.Models.SecurityLog.get_OfficerList() + 返回OfficerList.GetOfficerList(); Microsoft.AspNetCore.Mvc.ViewFeatures.ExpressionMetadataProvider + <> c__DisplayClass0_0.g__modelAccessor | 0(对象容器) Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer.get_Model() Microsoft.AspNetCore.Mvc.ViewFeatures.TemplateBuilder..ctor(IViewEngine viewEngine,IViewBufferScope bufferScope,ViewContext viewContext, ViewDataDictionary viewData,ModelExplorer,modelExplorer,字符串 htmlFieldName,字符串templateName,bool readOnly,object AdditionalViewData) Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.GenerateDisplay(ModelExplorer modelExplorer,字符串htmlFieldName,字符串templateName,对象 AdditionalViewData) Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.DisplayFor(Expression>表达式,字符串templateName,字符串htmlFieldName, 对象AdditionalViewData) Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperDisplayExtensions.DisplayFor(IHtmlHelper htmlHelper,Expression>表达式) SecurityCore.Pages.SecurityLogs.Pages_SecurityLogs_Index.ExecuteAsync() 在Index.cshtml中 + @ Html.DisplayFor(modelItem => item.OfficerList)Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage 页面,ViewContext上下文) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage 页,ViewContext上下文,布尔invokeViewStarts) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext 上下文) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext,字符串contentType,可空statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext,字符串contentType,可空statusCode) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 29_0(ResourceInvoker调用程序,任务lastTask,状态下一个, 作用域作用域,对象状态,布尔值已完成) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed 上下文) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext(下一个参考状态,参考作用域范围,参考对象状态,参考 bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 24_0(ResourceInvoker 调用者,任务lastTask,状态下一个,作用域范围,对象状态,布尔 完成了) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed 上下文) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(参考状态 接下来,ref Scope范围,ref对象状态,ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 19_0(ResourceInvoker 调用者,任务lastTask,状态下一个,作用域范围,对象状态,布尔 完成了) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 17_1(ResourceInvoker 调用者) Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask | 6_0(Endpoint 端点,任务请求任务,ILogger记录器) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext 上下文) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)

更新-添加关系

public class SecurityCoreContext : DbContext
{
    public SecurityCoreContext (DbContextOptions<SecurityCoreContext> options)
        : base(options)
    {
    }

    public DbSet<SecurityCore.Models.SecurityLog> SecurityLog { get; set; }

    public DbSet<SecurityCore.Models.Entity> Entity { get; set; }

    public DbSet<SecurityCore.Models.Location> Location { get; set; }

    public DbSet<SecurityCore.Models.ShiftRange> ShiftRange { get; set; }

    public DbSet<SecurityCore.Models.EventType> EventType { get; set; }

    public DbSet<SecurityCore.Models.SecurityLogOfficer> SecurityLogOfficer { get; set; }

    public DbSet<SecurityCore.Models.Officer> Officer { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SecurityLogOfficer>()
            .HasKey(t => new { t.SecurityLogID, t.OfficerID });

        modelBuilder.Entity<SecurityLogOfficer>()
            .HasOne(pt => pt.SecurityLog)
            .WithMany(p => p.SecurityLogOfficers)
            .HasForeignKey(pt => pt.SecurityLogID);

        modelBuilder.Entity<SecurityLogOfficer>()
            .HasOne(pt => pt.Officer)
            .WithMany(t => t.SecurityLogOfficers)
            .HasForeignKey(pt => pt.OfficerID);
    }

}

更新2020年1月23日

我试图根据以下答案更新代码,但是我认为这真的很接近要解决。在OfficerList类内部,当前没有SecLog b / c的值,直到单击搜索按钮后,页面加载中才有数据。

 OfficerList officerList = new OfficerList();
 OfficerLists = officerList.GetOfficerList(_context);

 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)
    .AsNoTracking(), pageIndex ?? 1, pageSize);

去到OfficerList类时为空

var SecLog = _context.SecurityLog.ToList();

SqlNullValueException:数据为Null。不能在Null值上调用此方法或属性。 Microsoft.Data.SqlClient.SqlBuffer.ThrowIfNull() Microsoft.Data.SqlClient.SqlBuffer.get_DateTime() Microsoft.Data.SqlClient.SqlDataReader.GetDateTime(int i) lambda_method(Closure,QueryContext,DbDataReader,ResultContext, int [],ResultCoordinator) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable + Enumerator.MoveNext() System.Collections.Generic.List..ctor(IEnumerable集合) System.Linq.Enumerable.ToList(IEnumerable源) SecurityCore.Models.OfficerList.GetOfficerList(SecurityCoreContext _context)在OfficerList.cs中 + var SecLog = _context.SecurityLog.ToList(); SecurityCore.Pages.SecurityLogs.IndexModel.OnGetAsync(string sortOrder,字符串currentFilter,字符串searchString,Nullable pageIndex,字符串entitySelect,字符串entityFilter,DateTime dateBegin,DateTime dateBeginSelect,DateTime dateEnd,DateTime index.cshtml.cs中的dateEndSelect) + OfficerLists = OfficerList.GetOfficerList(_context);

OfficialList类中是否有一种方法可以不遍历foreach中的SecurityLog,并以某种方式将SecurityLog的ID作为第二个参数传递给OfficerList(和_context)?

enter image description here

2 个答案:

答案 0 :(得分:1)

我发现您在OfficeList和SecurityLog类中多次使用了依赖项注入。这应该是导致错误的主要原因

我建议您只需在PageModel中使用依赖项注入,将_context作为参数传递给GetOfficerList方法,并且我认为不需要让OfficeList继承SecurityLog类。

返回OfficeIDs集合后,请使用PageModel中的OfficerLists字段来存储集合,并将SecurityLog数据集合存储到SecurityLog字段中。

同时,我在您的GetOfficerList方法中发现了一些错误。您可以直接参考以下代码进行测试。

PageModel:

public class HomeModel : PageModel
{ 
    private readonly SecurityCoreContext _context;
    public HomeModel(SecurityCoreContext context)
    {
        _context = context;
    }

    public List<string> OfficerLists { get; set; }
    public IList<SecurityLog> SecurityLog { get; set; }

    public async Task<IActionResult> OnGetAsync()
     {
        OfficerList officerList = new OfficerList();
        OfficerLists = officerList.GetOfficerList(_context);
        SecurityLog = await _context.SecurityLog.AsNoTracking().ToListAsync();
        return Page();
    }
}

OfficerList.cs

public class OfficerList
{
    public List<string> GetOfficerList(SecurityCoreContext _context)
    {
        List<string> OfficerIDs = new List<string>();

        //use the syntax .ToList() to convert object read from db to list to avoid being re-read again
        var SecLog = _context.SecurityLog.ToList();
        var SecLogOfficer = _context.SecurityLogOfficer.ToList();
        var Officer = _context.Officer.ToList();

        int rowID;
        rowID = 0;
        foreach (SecurityLog sl in SecLog)
        {
            int count = SecLogOfficer.Where(slo => slo.SecurityLogID == sl.ID).Count();
            if (count > 0)
            {
                OfficerIDs.Add("");
            }
            foreach (SecurityLogOfficer slo in SecLogOfficer.Where(slo => slo.SecurityLogID == sl.ID))
            {
                OfficerIDs[rowID] = OfficerIDs[rowID] + slo.Officer.FirstName + ", ";
            }
            if (count > 0)
            {
                OfficerIDs[rowID] = OfficerIDs[rowID].Substring(0, OfficerIDs[rowID].Length - 2);
            }
            rowID++;
        } 
        return OfficerIDs;

    }
}

页面:

@page
@model WebApplication_core_razorpage.Pages.HomeModel
@{
    ViewData["Title"] = "Home";
    Layout = "~/Pages/Shared/_Layout.cshtml";
    var i = 0;
}

<h1>Home</h1>

<table>
    @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.OfficerLists[i]
            </td>
        </tr>
        i++;
    }

</table>

这是此演示的结果:

https://i.stack.imgur.com/sz2LA.png

答案 1 :(得分:1)

我能够修改@Yongqing Yu的建议代码,以使军官列表正确显示。我决定将ID传递给OfficerList类,并进行排序设置,以便为每一行获取正确的官员列表。

我最初并未发布此逻辑,但是我可以基于Microsoft Contoso University的演示进行排序,搜索和分页。
https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-3.1

使用新实现的代码,排序和过滤不再适用于人员列表。其他一切都按需工作。

如何在下面的当前代码中解决排序和搜索? 更具体地说,...我如何阅读(迭代)OfficerID列表并搜索每个列表项(连接的人员列表行)的字符串值?

foreach (SecurityLog secLog in SecurityLog)
        {
            secLogCopy = secLog;

            OfficerLists = officerList.GetOfficerList(_context, secLog, rowID, OfficerIDs);
            if (!String.IsNullOrEmpty(searchString))
            {
                sort = sort.Where(s => OfficerIDs.ToString().Contains(searchString));
            }
            rowID++;
        }

PageModel:

namespace SecurityCore.Pages.SecurityLogs
{
    public class IndexModel : PageModel
    {
        private readonly SecurityCore.Models.SecurityCoreContext _context;

        public IndexModel(SecurityCore.Models.SecurityCoreContext context)
        {
            _context = context;
        }

        public string EventDateSort { get; set; }
        public string EventStartSort { get; set; }
        public string EventEndSort { get; set; }
        public string ContactNameSort { get; set; }
        public string EventTypeSort { get; set; }
        public string ShiftRangeSort { get; set; }

        public string CurrentSort { get; set; }
        public string IDSort { get; set; }

        [DataType(DataType.Date)]
        public Nullable<DateTime> DateEnd { get; set; }
        [DataType(DataType.Date)]
        public Nullable<DateTime> DateBegin { get; set; }
        public Entity Entity { get; set; }


        public PaginatedList<SecurityLog> SecurityLog { get; set; }
        public List<secLog> SecurityLogOfficers { get; set; } = new List<secLog>();
        public List<string> OfficerLists { get; set; }

        [BindProperty]
        public OfficerList officerList { get; set; } = new OfficerList();
        [BindProperty]
        public List<string> OfficerIDs { get; set; } = new List<string>();







    public async Task OnGetAsync(string sortOrder, string currentFilter, string searchString, int? pageIndex,
                                 string entitySelect, string entityFilter, DateTime dateBegin, DateTime dateBeginSelect, DateTime dateEnd, DateTime dateEndSelect)
    {
        selectedEntity = new SelectList(_context.Entity.Where(a => a.Active == "Y"), "Name", "Name");

        CurrentSort = sortOrder;
        IDSort = sortOrder == "ID" ? "ID_Desc" : "ID";
        EventDateSort = sortOrder == "EventDate" ? "EventDate_Desc" : "EventDate";
        ContactNameSort = sortOrder == "ContactName" ? "ContactName_Desc" : "ContactName";
        EventTypeSort = sortOrder == "EventType" ? "EventType_Desc" : "EventType";
        ShiftRangeSort = sortOrder == "ShiftRange" ? "ShiftRange_Desc" : "ShiftRange";            
        OfficerNameSort = sortOrder == "OfficerName" ? "OfficerName_Desc" : "OfficerName";


        IQueryable<SecurityLog> sort = from s in _context.SecurityLog select s;


        switch (sortOrder)
        {
            case "ID_Desc":
                sort = sort.OrderByDescending(s => s.ID);
                break;
            case "ID":
                sort = sort.OrderBy(s => s.ID);
                break;
            case "EventDate":
                sort = sort.OrderBy(s => s.EventDate);
                break;                
            case "ShiftRange":
                sort = sort.OrderBy(s => s.ShiftRange.Name).ThenBy(s => s.EventDate);
                break;
            case "ShiftRange_Desc":
                sort = sort.OrderByDescending(s => s.ShiftRange.Name).ThenBy(s => s.EventDate);
                break;
            case "EventType":
                sort = sort.OrderBy(s => s.EventType.Name).ThenBy(s => s.EventDate);
                break;
            case "EventType_Desc":
                sort = sort.OrderByDescending(s => s.EventType.Name).ThenBy(s => s.EventDate);
                break;                
            case "OfficerName":                    
                sort = sort.OrderBy(s => officerList.ToString()).ThenBy(s => s.EventDate);
                break;
            case "OfficerName_Desc":                    
                sort = sort.OrderByDescending(s => officerList.ToString()).ThenBy(s => s.EventDate);
                break;
            default:
                sort = sort.OrderByDescending(s => s.EventDate);
                break;
        }

        int pageSize = 5;





        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)                                    
        .AsNoTracking(), pageIndex ?? 1, pageSize);



        int rowID;
        rowID = 0;


        foreach (SecurityLog secLog in SecurityLog)
        {
            secLogCopy = secLog;
            OfficerLists = officerList.GetOfficerList(_context, secLog, rowID, OfficerIDs);
            if (!String.IsNullOrEmpty(searchString))
            {
                sort = sort.Where(s => OfficerIDs.ToString().Contains(searchString));
            }
            rowID++;
        }



        if (!String.IsNullOrEmpty(searchString))
        {                                                

            sort = sort.Where(s => s.Narrative.Contains(searchString)
                                || s.RecordLocked.Contains(searchString)
                                || s.ContactName.Contains(searchString)
                                || s.Location.Name.Contains(searchString)
                                || s.EventType.Name.Contains(searchString)
                                || s.ShiftRange.Name.Contains(searchString)
                                || s.ID.ToString().Contains(searchString)
                                || s.SubjectFirst.Contains(searchString)
                                || s.SubjectLast.Contains(searchString));                                    
        }

    }

}

}

OfficerList.cs

public class OfficerList
{
    public List<string> GetOfficerList(SecurityCoreContext _context, SecurityLog secLog, int rowID, List<string> OfficerIDs)
    {            

        int CurrentID = secLog.ID;

        var SecLogOfficer = _context.SecurityLogOfficer.ToList();
        var Officer = _context.Officer.ToList();


        int count = SecLogOfficer.Where(slo => slo.SecurityLogID == CurrentID).Count();

        if (count >= 0)
        {
            OfficerIDs.Add("");
        }
        foreach (secLog slo in SecLogOfficer.Where(slo => slo.SecurityLogID == CurrentID))
        {
            OfficerIDs[rowID] = OfficerIDs[rowID] + slo.Officer.FullName + ", ";
        }
        if (count > 0)
        {
            OfficerIDs[rowID] = OfficerIDs[rowID].Substring(0, OfficerIDs[rowID].Length - 2);
        }


        return OfficerIDs;

    }

}

页面:

@page
@model WebApplication_core_razorpage.Pages.HomeModel
@{
    ViewData["Title"] = "Home";
    Layout = "~/Pages/Shared/_Layout.cshtml";
    var i = 0;
}

<h1>Home</h1>

<table>
    @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.OfficerLists[i]
            </td>
        </tr>
        i++;
    }

</table>

PaginatedList.cs

public class PaginatedList<T> : List<T>
{
    public int PageIndex { get; private set; }
    public int TotalPages { get; private set; }        

    public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
    {
        PageIndex = pageIndex;
        TotalPages = (int)Math.Ceiling(count / (double)pageSize);

        this.AddRange(items);
    }

    public bool HasPreviousPage
    {
        get
        {
            return (PageIndex > 1);
        }
    }


    public bool HasNextPage => PageIndex < TotalPages;

    public bool ShowFirst
    {
        get
        {
            return (PageIndex != 1);
        }
    }

    public bool ShowLast
    {
        get
        {
            return (PageIndex != TotalPages);
        }
    }

    public static async Task<PaginatedList<T>> CreateAsync(
        IQueryable<T> source, int pageIndex, int pageSize)
    {
        var count = await source.CountAsync();
        var items = await source.Skip(
            (pageIndex - 1) * pageSize)
            .Take(pageSize).ToListAsync();
        return new PaginatedList<T>(items, count, pageIndex, pageSize);
    }
}