Rob*_*b C 5 c# asp.net-core razor-pages
我的项目中有多个模型,但在下面的屏幕中,大多数字段/属性都位于 SecurityLog 模型中。
下面是我显示连接的军官列表的地方。除了官员姓名之外,我的搜索和列标题排序可以正常工作。我很难合并官员姓名 b/c 列表来自另一个页面模型。
这是我的数据库架构和示例结果
我可以根据 Microsoft 的 Contoso 大学的演示来实现排序、搜索和分页。
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++;
}
Run Code Online (Sandbox Code Playgroud)
页面模型:
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 CurrentSort { 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;
EventDateSort = sortOrder == "EventDate" ? "EventDate_Desc" : "EventDate";
OfficerNameSort = sortOrder == "OfficerName" ? "OfficerName_Desc" : "OfficerName";
IQueryable<SecurityLog> sort = from s in _context.SecurityLog select s;
switch (sortOrder)
{
case "EventDate":
sort = sort.OrderBy(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.ContactName.Contains(searchString)
|| s.SubjectFirst.Contains(searchString)
|| s.SubjectLast.Contains(searchString));
}
}
}
Run Code Online (Sandbox Code Playgroud)
}
官员名单.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;
}
}
Run Code Online (Sandbox Code Playgroud)
页:
@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>
Run Code Online (Sandbox Code Playgroud)
分页列表.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);
}
}
Run Code Online (Sandbox Code Playgroud)
安全日志文件
namespace SecurityCore.Models
{
public class SecurityLog
{
[BindProperty(SupportsGet = true)]
public int ID { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
[Display(Name = "Event Date")]
public System.DateTime EventDate { get; set; }
public virtual Officer Officer { get; set; }
public virtual List<secLog> SecurityLogOfficers { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
关系
public class SecurityCoreContext : DbContext
{
public SecurityCoreContext (DbContextOptions<SecurityCoreContext> options)
: base(options)
{
}
public DbSet<SecurityCore.Models.SecurityLog> SecurityLog { get; set; }
public DbSet<SecurityCore.Models.secLog> SecurityLogOfficer { get; set; }
public DbSet<SecurityCore.Models.Officer> Officer { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<secLog>()
.HasKey(t => new { t.SecurityLogID, t.OfficerID });
modelBuilder.Entity<secLog>()
.HasOne(pt => pt.SecurityLog)
.WithMany(p => p.SecurityLogOfficers)
.HasForeignKey(pt => pt.SecurityLogID);
modelBuilder.Entity<secLog>()
.HasOne(pt => pt.Officer)
.WithMany(t => t.SecurityLogOfficers)
.HasForeignKey(pt => pt.OfficerID);
}
}
Run Code Online (Sandbox Code Playgroud)
说到文章和作者,当每篇文章可能有很多作者时,假设您要根据 a 进行搜索term并找到文章名称或文章摘要中包含该术语的文章,或者该文章的作者之一在其名称中包含该术语名字或他们的姓氏。
EF 6 - 多对五,没有关系的实体类
您可以使用 处理 Linq 查询中的这些情况,与使用Any处理 SQL 查询的方式相同EXISTS:
Where(article=> article.Title.Contains(term) ||
article.Abstract.Contains(term) ||
article.Authors.Any(author =>
author.FirstName.Contains(term) ||
author.LastName.Contains(searchTerm)))
Run Code Online (Sandbox Code Playgroud)
它并不完全生成以下 SQL 查询,但其逻辑与 SQL 中的以下内容非常相似:
FROM Articles
WHERE (Articles.Title LIKE '%' + @Term + '%') OR
(Articles.Abstract LIKE '%' + @Term + '%') OR
EXISTS (SELECT * FROM Authors
WHERE (Authors.FirstName LIKE '%' + @Term + '%') OR
(Authors.LastName LIKE '%' + @Term + '%'))
Run Code Online (Sandbox Code Playgroud)
EF CORE - Many-To-May 与关系的实体类
目前,尚不支持没有实体类来表示连接表的多对多关系。
您可以在 Linq 查询中使用 处理这些情况Any,与使用EXISTS+在 SQL 查询中处理的方式相同Join:
.Where(article => article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.ArticlesAuthors.Any(au =>
(au.Author.FirstName).Contains(model.SearchTerm) ||
(au.Author.LastName).Contains(model.SearchTerm)))
Run Code Online (Sandbox Code Playgroud)
它并不完全生成以下 SQL 查询,但其逻辑与 SQL 中的以下内容非常相似:
FROM Articles
WHERE (Articles.Title LIKE '%' + @Term + '%') OR
(Articles.Abstract LIKE '%' + @Term + '%') OR
EXISTS (SELECT * FROM ArticlesAuthors
INNER JOIN Authors
ON ArticlesAuthors.AuthorId = Authors.Id
WHERE ((Authors.FirstName LIKE '%' + @Term + '%') OR
(Authors.LastName LIKE '%'+ @Term + '%')) AND
(Articles.Id = ArticlesAuthors.ArticleId))
Run Code Online (Sandbox Code Playgroud)
问题有点混乱,包括搜索排序和大量代码,需要更多关注。为了使它对您和功能读者更有用和更容易理解,我将使用一个更简单的模型,它的属性更少,更容易理解。
正如您在 EF 图中所见,该ArticlesAuthors表并未显示在图中,因为它是一个多对多关系,仅包含其他实体的 Id 列,没有任何额外字段
我们要根据找到的文章SerachTerm,PublishDateFrom以及PublishDateTo:
PublishDateFrom,文章应该是结果的一部分,如果发布日期小于或等于PublishDateTo,文章应该是结果的一部分。这是一个搜索模型:
public class ArticlesSearchModel
{
public string SearchTerm { get; set; }
public DateTime? PublishDateFrom { get; set; }
public DateTime? PublishDateTo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
下面是搜索代码:
请注意:
Inculde与搜索无关,仅用于在输出结果中包含相关实体。
public class ArticlesBusinessLogic
{
public IEnumerable<Article> Search(ArticlesSearchModel model)
{
using (var db = new ArticlesDBEntities())
{
var result = db.Articles.Include(x => x.Authors).AsQueryable();
if (model == null)
return result.ToList();
if (!string.IsNullOrEmpty(model.SearchTerm))
result = result.Where(article => (
article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.Authors.Any(author =>
(author.FirstName + " " + author.LastName).Contains(model.SearchTerm))
));
if (model.PublishDateFrom.HasValue)
result = result.Where(x => x.PublishDate >= model.PublishDateFrom);
if (model.PublishDateFrom.HasValue)
result = result.Where(x => x.PublishDate <= model.PublishDateTo);
return result.ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如我上面提到的,目前尚不支持没有实体类来表示连接表的多对多关系,因此使用 EF CORE 的模型将是:
下面是搜索代码:
请注意:
Inculde与搜索无关,仅用于在输出结果中包含相关实体。
public IEnumerable<Article> Search(ArticlesSearchModel model)
{
using (var db = new ArticlesDbContext())
{
var result = db.Articles.Include(x=>x.ArticleAuthor)
.ThenInclude(x=>x.Author)
.AsQueryable();
if (model == null)
return result;
if (!string.IsNullOrEmpty(model.SearchTerm))
{
result = result.Where(article => (
article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.ArticleAuthor.Any(au =>
(au.Author.FirstName + " " + au.Author.LastName)
.Contains(model.SearchTerm))
));
}
if (model.PublishDateFrom.HasValue)
{
result = result.Where(x => x.PublishDate >= model.PublishDateFrom);
}
if (model.PublishDateFrom.HasValue)
{
result = result.Where(x => x.PublishDate <= model.PublishDateTo);
}
return result.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
你做错了很多事情:
.ToString()在类或列表上使用。所以首先你必须删除或更改这些行。例如 : sort = sort.Where(s => OfficerIDs.ToString().Contains(searchString));
sort = sort.OrderBy(s => officerList.ToString()).ThenBy(s => s.EventDate);
sort = sort.OrderByDescending(s => officerList.ToString()).ThenBy(s => s.EventDate);
Run Code Online (Sandbox Code Playgroud)
每次加载页面或更改搜索或排序时,您几乎都会从数据库表中加载整个数据。当然,有了分页,这个问题就变得有点模糊了
您没有使用实体框架来加载关系数据,因此您无法编写加载您需要的内容或用户搜索的内容的查询。(您正在从数据库的不同部分获取数据)
我知道这不是你想要的,但老实说,我试图回答你的问题并帮助你解决问题,但我最终又重写了整个事情......你应该将你的问题分解成更小的部分并提出一个更概念性的问题。
| 归档时间: |
|
| 查看次数: |
336 次 |
| 最近记录: |