基于SqlSugar的开发框架循序渐进介绍(31)-- 在查询接口中实现多表联合和单表对象的统一处理

基于,sqlsugar,开发,框架,循序渐进,介绍,查询,口中,实现,联合,对象,统一,处理 · 浏览次数 : 805

小编点评

**生成内容时需要带简单的排版** **1.定义数据类型** - `CrmStaticsDto` 用于存储每个属性的信息,包括label、typeName、count、category、dateStart、dateEnd等 - `List` 用于存储所有统计信息 **2.获取数据** - `GetStatics` 方法获取所有统计信息,并将其存储在`CrmStaticsDto`列表中 - `AddTreeData` 方法递归添加每个统计信息到树形列表中 **3.展示数据** - `InitTree` 方法递归构建树形列表,并将其添加到`treeView1`中 - `BindData` 方法设置所有记录数和列表数据源,并将其添加到`treeView1`中 **4.设置属性值** - 为每个属性设置对应的节点文本、类别信息等 - 为统计信息设置对应的节点属性值 **5.控制格式** - 设置节点字体大小、颜色等 - 设置节点间距 - 设置树形列表的展开展开效果 **示例代码** ```csharp //定义CrmStaticsDto public class CrmStaticsDto { public string Label { get; set; } public string TypeName { get; set; } public long Count { get; set; } public string Category { get; set; } public DateTime? DateStart { get; set; } public DateTime? DateEnd { get; set; } public CListItem Creator { get; set; } public List children { get; set; } } //添加统计数据 public async Task AddTreeData(List staticsList, TreeNode parentNode = null) { //获取所有统计信息 foreach (var info in staticsList) { //创建节点 var node = new TreeNode(info.Label, i, i); node.Tag = info; node.Text = info.Label; //递归添加子节点 await AddTreeData(info.children, node); if (parentNode != null) { parentNode.Nodes.Add(node); //加入父节点 } } } ```

正文

在一些复杂的业务表中间查询数据,有时候操作会比较复杂一些,不过基于SqlSugar的相关操作,处理的代码会比较简单一些,以前我在随笔《基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理》介绍过基于主表和中间表的联合查询,而往往实际会比这个会复杂一些。本篇随笔介绍联合多个表进行查询以及树形列表的条件展示的处理实现,系统能够给大家一些参考思路。

1、SqlSugar的开发框架的数据查询处理

在随笔《基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理》中,介绍过两个表的联合查询,如下所示代码所示。

/// <summary>
/// 根据用户ID获取对应的角色列表
/// </summary>
/// <param name="userID">用户ID</param>
/// <returns></returns>
private async Task<List<RoleInfo>> GetByUser(int userID)
{
    var query = this.Client.Queryable<RoleInfo, User_RoleInfo>(
    (t, m) => t.Id == m.Role_ID && m.User_ID == userID)
    .Select(t => t); //联合条件获取对象

    query = query.OrderBy(t => t.CreateTime);//排序
    var list = await query.ToListAsync();//获取列表
    return list;
}

/// <summary>
/// 根据机构获取对应的角色列表(判断机构角色中间表)
/// </summary>
/// <param name="ouID">机构的ID</param>
/// <returns></returns>
public async Task<List<RoleInfo>> GetRolesByOu(int ouID)
{
    var query = this.Client.Queryable<RoleInfo, OU_RoleInfo>(
    (t, m) => t.Id == m.Role_ID && m.Ou_ID == ouID)
    .Select(t => t); //联合条件获取对象

    query = query.OrderBy(t => t.CreateTime);//排序
    var list = await query.ToListAsync();//获取列表
    return list;
}

我们对于后端的数据查询,一般都是传入一个条件对象,通过条件类的属性进行构建查询信息,如下简单的处理操作。

/// <summary>
/// 应用层服务接口实现
/// </summary>
public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService
{
    /// <summary>
    /// 自定义条件处理
    /// </summary>
    /// <param name="input">查询条件Dto</param>
    /// <returns></returns>
    protected override ISugarQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
    {
        var query = base.CreateFilteredQueryAsync(input);

        query = query
            .WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID
            .WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
                                                                                         //年龄区间查询
            .WhereIF(input.AgeStart.HasValue, s => s.Age >= input.AgeStart.Value)
            .WhereIF(input.AgeEnd.HasValue, s => s.Age <= input.AgeEnd.Value)

            //创建日期区间查询
            .WhereIF(input.CreateTimeStart.HasValue, s => s.CreateTime >= input.CreateTimeStart.Value)
            .WhereIF(input.CreateTimeEnd.HasValue, s => s.CreateTime <= input.CreateTimeEnd.Value)
            ;

        return query;
    }

上面的 CreateFilteredQueryAsync 方法是一个基类函数,主要是构建该业务表的一些数据查询的匹配处理,如对于复杂一些的查询条件,这个内容会增加很多,不过都是可以通过代码生成工具基于数据库表字段来进行一一对应的生成,从而避免人工繁琐的敲击代码。

如下面是基类函数的常规条件查询和计数的函数处理。

/// <summary>
/// 根据条件获取列表
/// </summary>
/// <param name="input">分页查询条件</param>
/// <returns></returns>
public virtual async Task<PagedResultDto<TEntity>> GetListAsync(TGetListInput input)
{
    var query = CreateFilteredQueryAsync(input);
    var totalCount = await query.CountAsync();

    query = ApplySorting(query, input);
    query = ApplyPaging(query, input);

    var list = await query.ToListAsync();

    return new PagedResultDto<TEntity>(
       totalCount,
       list
   );
}

/// <summary>
/// 根据条件计算记录数量
/// </summary>
/// <param name="input">查询条件,忽略分页信息</param>
/// <returns></returns>
public virtual async Task<long> CountAsync(TGetListInput input)
{
    var query = CreateFilteredQueryAsync(input);

    var totalCount = await query.CountAsync();
    return totalCount; //返回符合条件的所有数量
}

上面的 CreateFilteredQueryAsync 方法一般会在具体的业务类中进行重写,从而实现具体条件的查询过滤。

 

2、对于多表的联合处理操作

而对于复杂的多表之间的联合查询处理,如果分开多个函数来实现,可能会比较麻烦,而且也不够统一,因此我们可以统一整合在CreateFilteredQueryAsync 实现。

而一些特殊的条件,我们可以在原有生成的条件分页类里面,增加更多的属性,用来在联合查询中赋值、或者获取值。如下图是我们额外增加的几个特殊的属性,用来在其他业务表中进行关联查询的字段。

由于客户分组是在另外一张表里面记录的,客户和分组之间的关联,是通过中间表的联合查询获得的。

 客户和供应商也有一个中间表的关联关系,因此我们如何联合查询,根据条件,可以通过下面的代码进行联合查询获得。

            if (!input.GroupId.IsNullOrWhiteSpace())
            {
                // 联合 CustomerGroup_CustomerInfo 表进行查询
                query = this.Client.Queryable<CustomerInfo, CustomerGroup_CustomerInfo>(
                       (t, m) => t.Id == m.Customer_ID && m.CustomerGroup_ID == input.GroupId)
                       .Select(t => t).MergeTable(); //联合条件获取对象
            }       
            if(!input.SupplierId.IsNullOrEmpty())
            {
                query = this.Client.Queryable<CustomerInfo, Customer_SupplierInfo>(
                        (t, m) => t.Id == m.Customer_ID && m.Supplier_ID == input.SupplierId)
                        .Select(t => t).MergeTable(); //联合条件获取对象
            }

上面的代码,需要注意的是,不同表之间联合获得的结果,如果需要整合到主表进行的查询中,则需要使用 .MergeTable() 操作进行合并处理。

这种最终我们可以得到比较复杂一些的查询处理了。

        /// <summary>
        /// 自定义条件处理
        /// </summary>
        /// <param name="input">查询条件Dto</param>
        /// <returns></returns>
        protected override ISugarQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
        {
            var query = base.CreateFilteredQueryAsync(input);
            if (!input.GroupId.IsNullOrWhiteSpace())
            {
                // 联合 CustomerGroup_CustomerInfo 表进行查询
                query = this.Client.Queryable<CustomerInfo, CustomerGroup_CustomerInfo>(
                       (t, m) => t.Id == m.Customer_ID && m.CustomerGroup_ID == input.GroupId)
                       .Select(t => t).MergeTable(); //联合条件获取对象
            }       
            if(!input.SupplierId.IsNullOrEmpty())
            {
                query = this.Client.Queryable<CustomerInfo, Customer_SupplierInfo>(
                        (t, m) => t.Id == m.Customer_ID && m.Supplier_ID == input.SupplierId)
                        .Select(t => t).MergeTable(); //联合条件获取对象
            }

            //通过名称或代码查询,任一符合即可
            query = query.WhereIF(!input.NameOrCode.IsNullOrWhiteSpace(), t => t.Name.Contains(input.NameOrCode) || t.SimpleName.Contains(input.NameOrCode) || t.HandNo.Contains(input.NameOrCode));

            query = query
               .WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID
               .WhereIF(!input.HandNo.IsNullOrWhiteSpace(), t => t.HandNo.Contains(input.HandNo)) //如需要精确匹配则用Equals
                .WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
                .WhereIF(!input.SimpleName.IsNullOrWhiteSpace(), t => t.SimpleName.Contains(input.SimpleName)) //如需要精确匹配则用Equals
                .WhereIF(!input.Province.IsNullOrWhiteSpace(), t => t.Province.Contains(input.Province)) //如需要精确匹配则用Equals
                .WhereIF(!input.City.IsNullOrWhiteSpace(), t => t.City.Contains(input.City)) //如需要精确匹配则用Equals
                .WhereIF(!input.District.IsNullOrWhiteSpace(), t => t.District.Contains(input.District)) //如需要精确匹配则用Equals
                .WhereIF(!input.Area.IsNullOrWhiteSpace(), t => t.Area.Contains(input.Area)) //如需要精确匹配则用Equals
                .WhereIF(!input.Address.IsNullOrWhiteSpace(), t => t.Address.Contains(input.Address)) //如需要精确匹配则用Equals
                .WhereIF(!input.ZipCode.IsNullOrWhiteSpace(), t => t.ZipCode.Contains(input.ZipCode)) //如需要精确匹配则用Equals
                .WhereIF(!input.Telephone.IsNullOrWhiteSpace(), t => t.Telephone.Contains(input.Telephone)) //如需要精确匹配则用Equals
                .WhereIF(!input.Fax.IsNullOrWhiteSpace(), t => t.Fax.Contains(input.Fax)) //如需要精确匹配则用Equals
                .WhereIF(!input.Contact.IsNullOrWhiteSpace(), t => t.Contact.Contains(input.Contact)) //如需要精确匹配则用Equals
                .WhereIF(!input.ContactPhone.IsNullOrWhiteSpace(), t => t.ContactPhone.Contains(input.ContactPhone)) //如需要精确匹配则用Equals
                .WhereIF(!input.ContactMobile.IsNullOrWhiteSpace(), t => t.ContactMobile.Contains(input.ContactMobile)) //如需要精确匹配则用Equals
                .WhereIF(!input.Email.IsNullOrWhiteSpace(), t => t.Email.Contains(input.Email)) //如需要精确匹配则用Equals
                .WhereIF(!input.QQ.IsNullOrWhiteSpace(), t => t.QQ.Contains(input.QQ)) //如需要精确匹配则用Equals
                .WhereIF(!input.Industry.IsNullOrWhiteSpace(), t => t.Industry.Contains(input.Industry)) //如需要精确匹配则用Equals
                .WhereIF(!input.BusinessScope.IsNullOrWhiteSpace(), t => t.BusinessScope.Contains(input.BusinessScope)) //如需要精确匹配则用Equals
                .WhereIF(!input.Brand.IsNullOrWhiteSpace(), t => t.Brand.Contains(input.Brand)) //如需要精确匹配则用Equals
                .WhereIF(!input.PrimaryClient.IsNullOrWhiteSpace(), t => t.PrimaryClient.Contains(input.PrimaryClient)) //如需要精确匹配则用Equals
                .WhereIF(!input.PrimaryBusiness.IsNullOrWhiteSpace(), t => t.PrimaryBusiness.Contains(input.PrimaryBusiness)) //如需要精确匹配则用Equals
                                                                                                                              //注册资金区间查询
               .WhereIF(input.RegisterCapitalStart.HasValue, s => s.RegisterCapital >= input.RegisterCapitalStart.Value)
               .WhereIF(input.RegisterCapitalEnd.HasValue, s => s.RegisterCapital <= input.RegisterCapitalEnd.Value)
               //营业额区间查询
               .WhereIF(input.TurnOverStart.HasValue, s => s.TurnOver >= input.TurnOverStart.Value)
               .WhereIF(input.TurnOverEnd.HasValue, s => s.TurnOver <= input.TurnOverEnd.Value)
                .WhereIF(!input.LicenseNo.IsNullOrWhiteSpace(), t => t.LicenseNo.Contains(input.LicenseNo)) //如需要精确匹配则用Equals
                .WhereIF(!input.Bank.IsNullOrWhiteSpace(), t => t.Bank.Contains(input.Bank)) //如需要精确匹配则用Equals
                .WhereIF(!input.BankAccount.IsNullOrWhiteSpace(), t => t.BankAccount.Contains(input.BankAccount)) //如需要精确匹配则用Equals
                .WhereIF(!input.LocalTaxNo.IsNullOrWhiteSpace(), t => t.LocalTaxNo.Contains(input.LocalTaxNo)) //如需要精确匹配则用Equals
                .WhereIF(!input.NationalTaxNo.IsNullOrWhiteSpace(), t => t.NationalTaxNo.Contains(input.NationalTaxNo)) //如需要精确匹配则用Equals
                .WhereIF(!input.LegalMan.IsNullOrWhiteSpace(), t => t.LegalMan.Contains(input.LegalMan)) //如需要精确匹配则用Equals
                .WhereIF(!input.LegalTelephone.IsNullOrWhiteSpace(), t => t.LegalTelephone.Contains(input.LegalTelephone)) //如需要精确匹配则用Equals
                .WhereIF(!input.LegalMobile.IsNullOrWhiteSpace(), t => t.LegalMobile.Contains(input.LegalMobile)) //如需要精确匹配则用Equals
                .WhereIF(!input.Source.IsNullOrWhiteSpace(), t => t.Source.Contains(input.Source)) //如需要精确匹配则用Equals
                .WhereIF(!input.WebSite.IsNullOrWhiteSpace(), t => t.WebSite.Contains(input.WebSite)) //如需要精确匹配则用Equals
                .WhereIF(!input.CompanyPictureGUID.IsNullOrWhiteSpace(), t => t.CompanyPictureGUID.Contains(input.CompanyPictureGUID)) //如需要精确匹配则用Equals
                .WhereIF(!input.CustomerType.IsNullOrWhiteSpace(), t => t.CustomerType.Contains(input.CustomerType)) //如需要精确匹配则用Equals
                .WhereIF(!input.Grade.IsNullOrWhiteSpace(), t => t.Grade.Contains(input.Grade)) //如需要精确匹配则用Equals
                .WhereIF(!input.CreditStatus.IsNullOrWhiteSpace(), t => t.CreditStatus.Contains(input.CreditStatus)) //如需要精确匹配则用Equals
                .WhereIF(!input.Importance.IsNullOrWhiteSpace(), t => t.Importance.Contains(input.Importance)) //如需要精确匹配则用Equals
                .WhereIF(input.IsPublic.HasValue, t => t.IsPublic == input.IsPublic) //如需要精确匹配则用Equals
                .WhereIF(input.Satisfaction.HasValue, t => t.Satisfaction == input.Satisfaction) //如需要精确匹配则用Equals
                .WhereIF(!input.Note.IsNullOrWhiteSpace(), t => t.Note.Contains(input.Note)) //如需要精确匹配则用Equals
                .WhereIF(input.TransactionCount.HasValue, t => t.TransactionCount == input.TransactionCount) //如需要精确匹配则用Equals
              
                //交易金额区间查询
               .WhereIF(input.TransactionTotalStart.HasValue, s => s.TransactionTotal >= input.TransactionTotalStart.Value)
               .WhereIF(input.TransactionTotalEnd.HasValue, s => s.TransactionTotal <= input.TransactionTotalEnd.Value)
               //首次交易时间区间查询
               .WhereIF(input.TransactionFirstDayStart.HasValue, s => s.TransactionFirstDay >= input.TransactionFirstDayStart.Value)
               .WhereIF(input.TransactionFirstDayEnd.HasValue, s => s.TransactionFirstDay <= input.TransactionFirstDayEnd.Value)
               //最近交易时间区间查询
               .WhereIF(input.TransactionLastDayStart.HasValue, s => s.TransactionLastDay >= input.TransactionLastDayStart.Value)
               .WhereIF(input.TransactionLastDayEnd.HasValue, s => s.TransactionLastDay <= input.TransactionLastDayEnd.Value)
               //最近联系日期区间查询
               .WhereIF(input.LastContactDateStart.HasValue, s => s.LastContactDate >= input.LastContactDateStart.Value)
               .WhereIF(input.LastContactDateEnd.HasValue, s => s.LastContactDate <= input.LastContactDateEnd.Value)
                                                                                                      
               //创建时间区间查询
               .WhereIF(input.CreateTimeStart.HasValue, s => s.CreateTime >= input.CreateTimeStart.Value)
               .WhereIF(input.CreateTimeEnd.HasValue, s => s.CreateTime <= input.CreateTimeEnd.Value)   
               //编辑时间区间查询
               .WhereIF(input.EditTimeStart.HasValue, s => s.EditTime >= input.EditTimeStart.Value)
               .WhereIF(input.EditTimeEnd.HasValue, s => s.EditTime <= input.EditTimeEnd.Value)

               .WhereIF(!input.Stage.IsNullOrWhiteSpace(), t => t.Stage.Contains(input.Stage)) //如需要精确匹配则用Equals
               .WhereIF(!input.Status.IsNullOrWhiteSpace(), s => s.Status == input.Status)
               .WhereIF(!input.Creator.IsNullOrWhiteSpace(), t => t.Creator.Contains(input.Creator)) //如需要精确匹配则用Equals
               .WhereIF(!input.Editor.IsNullOrWhiteSpace(), t => t.Editor.Contains(input.Editor)) //如需要精确匹配则用Equals
               .WhereIF(input.Deleted.HasValue, s => s.Deleted == input.Deleted)
               .WhereIF(!input.Dept_ID.IsNullOrWhiteSpace(), t => t.Dept_ID.Contains(input.Dept_ID)) //如需要精确匹配则用Equals
               .WhereIF(!input.Company_ID.IsNullOrWhiteSpace(), t => t.Company_ID.Contains(input.Company_ID)) //如需要精确匹配则用Equals
               .WhereIF(!input.MarkColor.IsNullOrWhiteSpace(), t => t.MarkColor.Contains(input.MarkColor)) //如需要精确匹配则用Equals
               .WhereIF(!input.ShareUsers.IsNullOrWhiteSpace(), t => t.ShareUsers.Contains(input.ShareUsers)) //如需要精确匹配则用Equals
               ;

            return query;
        }

有了这个丰富条件的处理,我们就可以在前端进行属性赋值就可以了,简单的调用后端通用的接口查询即可。

//构建分页的条件和查询条件
pagerDto = new CustomerPagedDto(this.winGridViewPager1.PagerInfo)
{
    //添加所需条件
    NameOrCode = this.txtCustomerNo.Text.Trim(),
    Deleted = 0
};

查询获得接口数据处理如下代码所示。

var result = await BLLFactory<ICustomerService>.Instance.GetListAsync(pagerDto);
return result;

在分页列表中展示获得的记录详细信息如下代码所示。

/// <summary>
/// 绑定列表数据
/// </summary>
private async void BindData()
{
    //entity
    this.winGridViewPager1.DisplayColumns = displayColumns;
    this.winGridViewPager1.ColumnNameAlias = await BLLFactory<ICustomerService>.Instance.GetColumnNameAlias();//字段列显示名称转义

    //获取分页数据列表
    var result = await GetData();

    //设置所有记录数和列表数据源
    this.winGridViewPager1.PagerInfo.RecordCount = result.TotalCount; //需先于DataSource的赋值,更新分页信息
    this.winGridViewPager1.DataSource = result.Items;
    this.winGridViewPager1.PrintTitle = "客户信息列表";
}

 

3、对于多种属性、状态条件的统一处理

我在之前介绍过的CRM系统主界面中,关于客户关系信息的展示的时候,是通过一个复杂的树形列表来承载不同属性来进行快速的查询,如下界面所示。

这些树形列表的属性信息,在SqlSugar开发框架中,我们统一进行生成,首先定义一个通用的承载对象,如下类所示。

/// <summary>
/// 对CRM的业务数据进行统计的一个公共类
/// </summary>
public class CrmStaticsDto
{
    /// <summary>
    /// 节点显示名称
    /// </summary>
    public string Label { get; set; }

    /// <summary>
    /// 属性名称
    /// </summary>
    public string TypeName { get; set; }

    /// <summary>
    /// 数量
    /// </summary>
    public long Count { get; set; }

    /// <summary>
    /// 业务分类
    /// </summary>
    public string Category { get; set; }

    /// <summary>
    /// 记录的日期开始
    /// </summary>
    public DateTime? DateStart { get; set; }
    /// <summary>
    /// 记录的日期结束
    /// </summary>
    public DateTime? DateEnd { get; set; }

    /// <summary>
    /// 创建人信息
    /// </summary>
    public CListItem Creator { get; set; }

    /// <summary>
    /// 子节点集合
    /// </summary>
    public List<CrmStaticsDto> children { get; set; } = new List<CrmStaticsDto>();
}

这个类似一个嵌套的集合,通过children进行添加更多的子集记录。

后端提供一个获取统计信息的树形列表的方法,如下定义所示。

        /// <summary>
        /// 获取列表统计信息
        /// </summary>
        /// <returns></returns>
        public async Task<List<CrmStaticsDto>> GetStatics(string compnayId)
{
................
}

但我们为它添加各种属性的时候,设置相关的节点文本、类别信息即可。

    //所有记录
    var allNode = new CrmStaticsDto()
    {
        Label = "所有记录"
    };
    list.Add(allNode);

    var propertyNode = new CrmStaticsDto()
    {
        Label = "客户属性分类"
    };
    list.Add(propertyNode);


    var typeName = "客户状态";
    var count = await baseQuery.Clone().CountAsync();//Clone()避免进行多次查询时,可能会出现结果不正确的问题
    var statusNode = new CrmStaticsDto()
    {
        Label = $"{typeName}({count})",
        Count = count,
        TypeName = typeName
    };
    var dict = await dictDataService.FindByDictType(typeName);
    foreach (var info in dict)
    {
        var value = info.Value;
        var subCount = baseQuery.Clone().Where(s => s.Status == value).Count();
        statusNode.children.Add(new CrmStaticsDto()
        {
            Label = $"{info.Name}({subCount})",
            Count = subCount,
            Category = info.Value,
            TypeName = typeName
        });
    }
    propertyNode.children.Add(statusNode);

这样我们在前端的WInform界面中展示树形列表的时候,就会变得非常简单,通过一个递归的函数就可以添加相关的节点信息了,如下代码所示。

private async void InitTree()
{
    this.treeView1.BeginUpdate();
    this.treeView1.Nodes.Clear();

    //获取所有的统计列表
    var staticsList = await BLLFactory<ICustomerService>.Instance.GetStatics(this.SelectedCompanyID);
    await AddTreeData(staticsList, null);

    //this.treeView1.ExpandAll();
    this.treeView1.EndUpdate();
}

private async Task AddTreeData(List<CrmStaticsDto> staticsList, TreeNode parentNode = null)
{
    var i = 0;
    if (staticsList != null)
    {
        foreach (var info in staticsList)
        {
            var node = new TreeNode(info.Label, i, i);
            node.Tag = info;
            node.Text = info.Label;

            await AddTreeData(info.children, node);

            if (parentNode == null)
            {
                this.treeView1.Nodes.Add(node); //如果是顶级处理,则treeView1节点加入
            }
            else
            {
                parentNode.Nodes.Add(node); //如果是递归的,则加到父节点上
            }
        }
    }
}

以上就是对联合多个表进行查询以及树形列表的条件展示的处理思路,系统能够给大家一些参考思路。

与基于SqlSugar的开发框架循序渐进介绍(31)-- 在查询接口中实现多表联合和单表对象的统一处理相似的内容:

基于SqlSugar的开发框架循序渐进介绍(31)-- 在查询接口中实现多表联合和单表对象的统一处理

在一些复杂的业务表中间查询数据,有时候操作会比较复杂一些,不过基于SqlSugar的相关操作,处理的代码会比较简单一些,以前我在随笔《基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理》介绍过基于主表和中间表的联合查询,而往往实际会比这个会复杂一些。本篇随笔介绍联合多个表进行查询以及树形列表的条件展示的处理实现,系统能够给大家一些参考思路。

基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍

工作流是集成系统的模块应用,使用权限管理系统的身份认证登录后即可使用。本篇随笔介绍工作流模块的界面功能效果。

基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理

在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间,这样验证短信验证码的时候,就会自动判断是否过期了。本篇随笔结合CSRedis的使用,介绍如何实现缓存的初始化及使用的处理。

基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面

我们开发一个系统,在保证风格统一、代码强壮、可读性强等基础上,还能够结合代码生成工具快速开发相关后端,以及各种前端界面的,无疑是非常好的,既保证了项目的代码质量,又能够极大的提高开发效率。代码生成工具Database2Sharp是在完善的开发项目上,抽取出数据变化的部分,通过演绎、归纳、反复演绎和归纳等提炼方式抽取出相关的规则,以工具的方式来快速提高生产率,使得我们在开发各种不同的项目上的时候,能

基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

在之前的SqlSugar系列随笔中,介绍了很多我们关于SqlSugar的开发框架的内容,SqlSugar的开发框架的目的是多前端应用场景,因此其中会包含各种不同的前端应用,前面介绍了基于DevExpress的Winform的前端应用,以及基于Vue3+TypeScript+ElementPlus的BS前端应用,本篇随笔继续介绍SqlSugar的开发框架的另一个前端应用,基于UniApp+Vue+T

基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件查询处理类似的处理过程,因此本篇随笔探讨两种不同查询在前端界面上的展示效果,以及后端基于.netCore的Web API端的基类进行的统一封装处理。

基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换

有时候,为了给前端页面输出内容,有时候我们需要准备和数据库不一样的实体信息,因为数据库可能记录的是一些引用的ID或者特殊字符,那么我们为了避免前端单独的进行转义处理,我们可以在后端进行统一的格式化后再行输出,后端处理可以采用不同的DTO尸体信息,后端对不同的实体进行映射处理即可,也可以采用同一个实体,在SqlSugar实体信息中忽略对应的字段写入实现,本篇随笔介绍后者的处理方式,实现在在工作流列表

基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理

在工作流页面中,除了特定的业务表单信息外,往往也需要同时展示通用申请单的相关信息,因此在页面设计的时候需要使用一些组件化的概念来实现动态的内容展示处理,本篇随笔介绍Vue3+TypeScript+ElementPus的前端工作流模块中实现统一的表单编辑和表单详情查看处理。

基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求

在前面随笔介绍的基于SqlSugar的WInform端管理系统中,数据提供者是直接访问数据库的方式,不过窗体界面调用数据接口获取数据的时候,我们传递的是标准的接口,因此可扩展性比较好。我曾经在随笔《基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转》中介绍过,该SqlSugar开发框架本身是基于IOC控制反转的,因此对于接入不同的数据提供者,只需要切换

基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化

在上篇随笔《基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求》中介绍了基于一个接口,实现对两种不同接入方式(直接访问数据库实现,基于Web API代理类实现)的处理,由于定义的接口中,我们为了方便,也是用了Lambda表达式的进行一些参数的处理,那么如果在Web API代理类中,Lambda表达式是不能直接传递给Web API的控