四时宝库

程序员的知识宝库

Blazor server小白笔记10-多条件查询与分页

这一篇满满的干货,基于真实SQL 2016数据库,实现bootstrapBlazor中table组件的分页和表外查询,table组件自带查询按钮和模版,但是总感觉没有外部自己实现的来的可控性强,需要先关注的问题如下。

需关注和了解的问题

  1. ef core下不确定多个查询条件下的查询,就是相对应的文本框中有内容就查,没内容就跳过
  2. ef core中三目运算符的使用,这是实现无内容时跳过的关键
  3. 外部按钮的查询事件怎么更新数据至Table组件中,也就是手动更新
@ref的使用,这是更新数据至table组件中的关键,决定了你在外部如何重用table组件

感谢这两位大神的贴子,我也是卡在这里好久没有解决

参考:https://www.cnblogs.com/ysmc/p/16128206.html

参考:https://blog.csdn.net/weixin_42511607/article/details/122283265

完整UI代码

在UI中注释掉了table组件中的搜索模板,并禁止显示搜索按钮,需要特别注意不要给Items绑定数据,否则查询后无法显示,在错误信息中会看到冲突。

OnQueryAsync事件一定要有,不能因为禁止显示按索按钮,就把查询事件也给不要了,查询事件在网页初始化时就会执行,同样外部按钮点击查询时也是调用的这个事件。

@ref="Table",同样非常重要,其中的Table不是组件名称,而是在C#代码中定义的private Table<Book>? Table { get; set; }

@page "/Demo5"
@using Blazor.OnlyServer1.Models;

<div style="height:10%">
    <GroupBox Title="搜索条件">
        <div class="row g-3 form-inline">
            <div class="col-auto col-form-label">
                <span>名称</span>
            </div>
            <div class="col-12 col-sm-2">
                <BootstrapInput @bind-Value="@name" PlaceHolder="搜索的名称" maxlength="50" ShowLabel="false" />
            </div>
            <div class="col-auto col-form-label">
                <span>规格</span>
            </div>
            <div class="col-12 col-sm-2">
                <BootstrapInput @bind-Value="@lx" PlaceHolder="请输入规格" maxlength="50" ShowLabel="false" />
            </div>
            <div class=" btn-group col-12 col-sm-2">
                <Button Text="搜索" OnClick="QueryBtn" Color="Color.Success" Icon="fas fa-arrows-rotate"></Button>
                <Button Text="重置" OnClick="ResetBtn" Color="Color.Warning" Icon="fas fa-eraser"></Button>
            </div>
            
        </div>
    </GroupBox>
</div>
<div style="height:90%">
    <Table TItem="Book"  PageItemsSource="PageItemsSource" IsFixedHeader="true" ShowSearch="false" ShowEmpty="true" SearchMode="SearchMode.Top" ShowSearchButton="false"
           IsPagination="true" AllowResizing="true" AutoGenerateColumns="true" ShowColumnList="true" EmptyText="亲,没有查询到需要的数据!" @ref="Table"
           IsStriped="true" IsBordered="true" OnResetSearchAsync="@OnResetSearchAsync"
           ShowToolbar="true" IsMultipleSelect="true" ShowExtendButtons="false"
           OnQueryAsync="@OnSerchAsync">
       @*  <SearchTemplate>
            <GroupBox Title="搜索条件">
                <div class="row g-3 form-inline">
                    <div class="col-auto col-form-label">
                        <span>名称</span>
                    </div>
                    <div class="col-12 col-sm-2">
                        <BootstrapInput @bind-Value="@name" PlaceHolder="搜索的名称" maxlength="50" ShowLabel="false"  />
                    </div>
                    <div class="col-auto col-form-label">
                        <span>规格</span>
                    </div>
                    <div class="col-12 col-sm-2">
                        <BootstrapInput @bind-Value="@lx" PlaceHolder="请输入规格" maxlength="50" ShowLabel="false"  />
                    </div>
                </div>
            </GroupBox>
        </SearchTemplate> *@
    </Table>
</div>

上面的代码中已经注释掉了Table组件自带的搜索模版,改为在Table组件外实现,记得进行双向数据绑定。

C#代码

代码中有一些没用的同样注释掉了,还有些事件用不到,如OnQueryAsync、OnResetSearchAsync,其实外部查询按钮就是在填好查询条件(不填写也能查询,在OnSerchAsync中进行处理就行了)后直接调用Table的查询,重置按钮就是把查询的条件清空,然后再调味用Table的查询

using Blazor.OnlyServer1.Models;
using BootstrapBlazor.Components;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using static System.Reflection.Metadata.BlobBuilder;

namespace Blazor.OnlyServer1.Components.Pages
{
    public partial class Demo5
    {
       //重要,用于绑定table组件和在外部访问table组件时使用到
        private Table<Book>? Table { get; set; }
        //分页的大小
        private static IEnumerable<int> PageItemsSource => new int[] { 2, 3 };
        private Book SearchModel { get; set; } = new Book();
        private List<Book> Books { get; set; }
        private  string name;
        private  string lx;
        private int TotalCount = 0;

        protected override void OnInitialized()
        {
            base.OnInitialized();
        }

        //Table外查询按钮事件
        private  async Task QueryBtn() 
        {
            await Table.QueryAsync(); //调用table的查询事件
        }

        //Table外重置按钮事件
        private async Task ResetBtn() 
        {
            name = "";
            lx = "";
            await Table.QueryAsync(); //调用table的查询事件
        }


        //基于数据库的分页查询
        private Task<QueryData<Book>> OnQueryAsync(QueryPageOptions options)
        {
            int TotalCount = 0;
            List<Book> books = new List<Book>();
            int skip = (options.PageIndex - 1) * options.PageItems;
            using (var context =new BookContext()) 
            {
                books = context.Books.Skip(skip).Take(options.PageItems).ToList();
                TotalCount = context.Books.Count();
            }
            return Task.FromResult(new QueryData<Book>()
            {
                Items = books,
                TotalCount = TotalCount,
            });

        }

        //点击搜索按钮时的查询,基于数据库分页
        private Task<QueryData<Book>> OnSerchAsync(QueryPageOptions options) 
        {
            
            int skip = (options.PageIndex - 1) * options.PageItems;

            //无数据时、无查询条件时显示全部的数据,并进行数据库分页
            if (Books == null || Books.Count() == 0||(string.IsNullOrEmpty(name) && string.IsNullOrEmpty(lx)))
            {
                using (var context = new BookContext())
                {
                    Books = context.Books.Skip(skip).Take(options.PageItems).ToList();
                    TotalCount = context.Books.Count();
                }
            }
            //处理高级搜索文本
            //if (!string.IsNullOrEmpty(options.SearchText))
            //{
            //    name = "";
            //    lx = "";
            //    using (var context = new BookContext())
            //    {
            //        Books = context.Books.Where(d => d.名称.Contains(options.SearchText) || d.规格.Contains(options.SearchText)).OrderByDescending(d => d.Id).Skip(skip).Take(options.PageItems).ToList();
            //        TotalCount = context.Books.Where(d => d.名称.Contains(options.SearchText) || d.规格.Contains(options.SearchText)).Count();
            //    }
            //}
 
           //查询条件有一个不为空时使用多个where加三目运算符来实现不确定查询条件有几个时的查询
          //查询条件的内容为空时设置true直接跳过
          if (!string.IsNullOrEmpty(name)||!string.IsNullOrEmpty(lx))
            {
                options.SearchText = "";
                using (var context = new BookContext())
                {
                    //查询符合条件的数据,并进行分页
                    Books=context.Books
                        .Where(d =>string.IsNullOrEmpty(name)?true:d.名称.Contains(name))
                        .Where(d=>string.IsNullOrEmpty(lx)?true:d.规格.Contains(lx))
                        .Skip(skip).Take(options.PageItems).ToList();
                    //查询符合条件的数量,用于实现分页和显示数据量
                    TotalCount = context.Books
                        .Where(d => string.IsNullOrEmpty(name) ? true : d.名称.Contains(name))
                        .Where(d => string.IsNullOrEmpty(lx) ? true : d.规格.Contains(lx))
                        .Count();
                }
            }
            //处理自定义搜索的文本

            return Task.FromResult(new QueryData<Book>()
            {
                Items = Books,
                TotalCount = TotalCount,
            });
        }

        //重置搜索,Table内置
        private static Task OnResetSearchAsync(Book item)
        {
            return Task.CompletedTask;
        }
    }
}

好了,到此为止查询就基本上搞定了,想实现多字段查询就继续增加查询条件就可以了,也不用像原生SQL一样在那拼接条件字符串,经过这么些天的努力,感觉它终于像个能使用的东西了。



#职场##冬日生活打卡季##挑战30天在头条写日记#

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接