In my main index page, I would like to display a list of Officers in the Officer's Name column. i.e. Tommy Bahamas, Clinton K, etc...
I am having difficulty because the Officer and SecurityLogOfficer table are not a part of my SecurityLog model on the index page.
SecurityLog Index Page
@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>
}
I created a class, OfficerList, to return a list of comma separated Officers but I am having trouble displaying this on the SecurityLog index page.
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;
}
}
This is where I would like to display the concatenated list...
And here is my database schema and sample results
Any assistance would be appreciated. Thanks!
UPDATE
I am having an issue retrieving a list of concatenated names in my SecurityLog Model.
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();
}
}
}
Modified OfficerList class
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;
}
}
My _context for SecurityLog is saying that it is null.
SqlNullValueException: Data is Null. This method or property cannot be called on Null values. 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 collection) System.Linq.Enumerable.ToList(IEnumerable source) SecurityCore.Models.OfficerList.GetOfficerList() in OfficerList.cs + var SecLog = _context.SecurityLog.ToList(); SecurityCore.Models.SecurityLog.get_OfficerList() in SecurityLog.cs + return officerList.GetOfficerList(); Microsoft.AspNetCore.Mvc.ViewFeatures.ExpressionMetadataProvider+<>c__DisplayClass0_0.g__modelAccessor|0(object container) Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer.get_Model() Microsoft.AspNetCore.Mvc.ViewFeatures.TemplateBuilder..ctor(IViewEngine viewEngine, IViewBufferScope bufferScope, ViewContext viewContext, ViewDataDictionary viewData, ModelExplorer modelExplorer, string htmlFieldName, string templateName, bool readOnly, object additionalViewData) Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.GenerateDisplay(ModelExplorer modelExplorer, string htmlFieldName, string templateName, object additionalViewData) Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.DisplayFor(Expression> expression, string templateName, string htmlFieldName, object additionalViewData) Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperDisplayExtensions.DisplayFor(IHtmlHelper htmlHelper, Expression> expression) SecurityCore.Pages.SecurityLogs.Pages_SecurityLogs_Index.ExecuteAsync() in Index.cshtml + @Html.DisplayFor(modelItem => item.OfficerList) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
UPDATE - ADDING RELATIONSHIPS
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);
}
}
UPDATE 1/23/2020
I attempted to update the code based on the below answer and I think this is really close to being solved, however; inside of the OfficerList class there is not currently a value for SecLog b/c there is no data on page load until the search button is clicked.
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);
This is null when going to OfficerList class
var SecLog = _context.SecurityLog.ToList();
SqlNullValueException: Data is Null. This method or property cannot be called on Null values. 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 collection) System.Linq.Enumerable.ToList(IEnumerable source) SecurityCore.Models.OfficerList.GetOfficerList(SecurityCoreContext _context) in OfficerList.cs + var SecLog = _context.SecurityLog.ToList(); SecurityCore.Pages.SecurityLogs.IndexModel.OnGetAsync(string sortOrder, string currentFilter, string searchString, Nullable pageIndex, string entitySelect, string entityFilter, DateTime dateBegin, DateTime dateBeginSelect, DateTime dateEnd, DateTime dateEndSelect) in Index.cshtml.cs + OfficerLists = officerList.GetOfficerList(_context);
Is there a way in the OfficerList class to not loop through SecurityLog in the foreach and somehow pass in the ID of the SecurityLog as a second parameter to OfficerList( along with _context)?
item.OfficerList
with all the officer within the SecurityLogId, then just iterate onitem.OfficerList
collection and display all the officer. – Arvind Maurya