基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中(2)

简介: 基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中(2)

在上篇随笔《基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中》中介绍了SqlSugar的基础用法,以及实现对常规项目中对数据访问的基类封装,并通过编写单元测试覆盖相关的功能测试,虽然最后编写单元测试的代码就是实际调用数据处理的代码,不过没有界面不太直观,本篇随笔继续深入SqlSugar的使用介绍,介绍基于Winform项目界面的整合测试。

1、数据访问层的实现

在上篇随笔,我们介绍了SqlSugar使用起来还是非常简单的,首先定义好和数据表对应的实体类信息,通过特性声明给的方式,声明表名和字段信息(包括主键信息)

如对于数据库表的标注:

[SugarTable("TB_DictData")]
public class DictDataInfo
{
}

以及对字段信息主键的标注

/// <summary>
        /// 编号
        /// </summary>
        [SugarColumn(IsPrimaryKey = true)]
        public virtual string ID { get; set; }

或者是自增字段的标注处理

public class Person 
    {
        //数据库字段
        [SugarColumn(IsPrimaryKey =true,IsIdentity =true)]
        public int Id { get; set; }

例如我们对于Winform开发框架中的字典数据库,设计关系如下所示。

我们生成器对应的SQLSugar实体信息如下所示,这些枯燥的工作可以交给配套的代码生成工具Database2sharp来完成。

/// <summary>
    /// DictTypeInfo
    /// </summary>
    [SugarTable("TB_DictType")]
    public class DictTypeInfo
    {
        /// <summary>
        /// 默认构造函数(需要初始化属性的在此处理)
        /// </summary>
        public DictTypeInfo()
        {
            this.ID = System.Guid.NewGuid().ToString();
            this.LastUpdated = System.DateTime.Now;
        }
        #region Property Members
        [SugarColumn(IsPrimaryKey = true)]
        public virtual string ID { get; set; }
        /// <summary>
        /// 类型名称
        /// </summary>
        public virtual string Name { get; set; }
        /// <summary>
        /// 字典代码
        /// </summary>
        public virtual string Code { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Remark { get; set; }
        /// <summary>
        /// 排序
        /// </summary>
        public virtual string Seq { get; set; }
        /// <summary>
        /// 编辑者
        /// </summary>
        public virtual string Editor { get; set; }
        /// <summary>
        /// 编辑时间
        /// </summary>
        public virtual DateTime LastUpdated { get; set; }
        /// <summary>
        /// 分类:0 客房/1 KTV/2 茶室
        /// </summary>
        public virtual string PID { get; set; }
        #endregion
    }

同时为了方便条件的分页处理,我们定义一个分页的Dto对象,如下所示。

/// <summary>
    /// 用于根据条件分页查询,DTO对象
    /// </summary>
    public class DictTypePagedDto : PagedAndSortedInputDto, IPagedAndSortedResultRequest
    {
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public DictTypePagedDto() : base() { }
        /// <summary>
        /// 参数化构造函数
        /// </summary>
        /// <param name="skip
       /// ">跳过的数量</param>
        /// <param name="resultCount">最大结果集数量</param>
        public DictTypePagedDto(int skipCount, int resultCount)
        {
        }
        /// <summary>
        /// 使用分页信息进行初始化SkipCount 和 MaxResultCount
        /// </summary>
        /// <param name="pagerInfo">分页信息</param>
        public DictTypePagedDto(PagerInfo pagerInfo) : base(pagerInfo)
        {
        }
        #region Property Members
        /// <summary>
        /// 不包含的对象的ID,用于在查询的时候排除对应记录
        /// </summary>
        public virtual string ExcludeId { get; set; }
        public virtual string Name { get; set; }
        public virtual string Code { get; set; }
        public virtual string Remark { get; set; }
        public virtual string Seq { get; set; }
        public virtual string PID { get; set; }
        /// <summary>
        /// 创建时间-开始
        /// </summary>
        public DateTime? CreationTimeStart { get; set; }
        /// <summary>
        /// 创建时间-结束
        /// </summary>
        public DateTime? CreationTimeEnd { get; set; }
        #endregion
    }

同理对于字典项目的实体信息,也是类似的定义方式,如下所示。

/// <summary>
    /// DictDataInfo
    /// </summary>
    [SugarTable("TB_DictData")]
    public class DictDataInfo
    {
        /// <summary>
        /// 默认构造函数(需要初始化属性的在此处理)
        /// </summary>
        public DictDataInfo()
        {
            this.ID = System.Guid.NewGuid().ToString();
            this.LastUpdated = System.DateTime.Now;
        }
        #region Property Members
        /// <summary>
        /// 编号
        /// </summary>
        [SugarColumn(IsPrimaryKey = true)]
        public virtual string ID { get; set; }
        /// <summary>
        /// 字典大类
        /// </summary>
        public virtual string DictType_ID { get; set; }
        /// <summary>
        /// 字典名称
        /// </summary>
        public virtual string Name { get; set; }
        /// <summary>
        /// 字典值
        /// </summary>
        public virtual string Value { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Remark { get; set; }
        /// <summary>
        /// 排序
        /// </summary>
        public virtual string Seq { get; set; }
        /// <summary>
        /// 编辑者
        /// </summary>
        public virtual string Editor { get; set; }
        /// <summary>
        /// 编辑时间
        /// </summary>
        public virtual DateTime LastUpdated { get; set; }
        #endregion
    }

最终我们定义完成实体信息后,需要集成上篇随笔提到的数据访问基类,并重写一下查询条件处理,排序的规则信息即可,如下代码所示。

/// <summary>
    /// 应用层服务接口实现
    /// </summary>
    public class DictTypeService : MyCrudService<DictTypeInfo, string, DictTypePagedDto>
    {
        /// <summary>
        /// 获取字段中文别名(用于界面显示)的字典集合
        /// </summary>
        /// <returns></returns>
        public override Task<Dictionary<string, string>> GetColumnNameAliasAsync()
        {
            var dict = new Dictionary<string, string>();
            #region 添加别名解析
            dict.Add("ID", "编号");
            dict.Add("Name", "类型名称");
            dict.Add("Code", "字典代码");
            dict.Add("Remark", "备注");
            dict.Add("Seq", "排序");
            dict.Add("Editor", "编辑者");
            dict.Add("LastUpdated", "编辑时间");
            dict.Add("PID", "父ID");
            #endregion
            return Task.FromResult(dict);
        }
        /// <summary>
        /// 自定义条件处理
        /// </summary>
        /// <param name="input">查询条件Dto</param>
        /// <returns></returns>
        protected override ISugarQueryable<DictTypeInfo> CreateFilteredQueryAsync(DictTypePagedDto input)
        {
            var query = base.CreateFilteredQueryAsync(input);
            query = query
                .WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.ID != input.ExcludeId) //不包含排除ID
                .WhereIF(!string.IsNullOrEmpty(input.Code), t => t.Code == input.Code)
                .WhereIF(!string.IsNullOrEmpty(input.PID), t => t.PID == input.PID)
                .WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
                .WhereIF(!input.Remark.IsNullOrWhiteSpace(), t => t.Remark.Contains(input.Remark)) //如需要精确匹配则用Equals
                .WhereIF(!input.Seq.IsNullOrWhiteSpace(), t => t.Seq.Contains(input.Seq)) //如需要精确匹配则用Equals
                //创建日期区间查询
                .WhereIF(input.CreationTimeStart.HasValue, s => s.LastUpdated >= input.CreationTimeStart.Value)
                .WhereIF(input.CreationTimeEnd.HasValue, s => s.LastUpdated <= input.CreationTimeEnd.Value)
                ;
            return query;
        }
        /// <summary>
        /// 自定义排序处理
        /// </summary>
        /// <param name="query">可查询LINQ</param>
        /// <param name="input">查询条件Dto</param>
        /// <returns></returns>
        protected override ISugarQueryable<DictTypeInfo> ApplySorting(ISugarQueryable<DictTypeInfo> query, DictTypePagedDto input)
        {
            return base.ApplySorting(query, input).OrderBy(s => s.Seq);
        }
    }

其中MyCrudService 采用了泛型的定义方式,传入对应的实体类,主键类型,以及排序分页的对象DTO等,方便基类实现强类型的接口处理。

这个子类我们也可以通过代码生成的方式实现批量生成即可。

整合到项目里面,把实体类和数据访问的服务类区分不同的目录放置,便于管理即可。

 

2、Winform界面的开发和调用数据操作处理

上面我们完成了数据库表的实体类和对应数据访问服务类的处理后,我们接下来的就是设计Winform界面用来处理相关的数据处理。

我这里把我的基于微软企业库访问模式的Winform界面部分拷贝过来调整一下,如下界面所示。

查看和编辑字典大类界面

 编辑字典项目

 

对于数据访问类的调用,我们使用了一个工厂类来创建对应的单例应用,如下获取字典大类列表。

/// <summary>
        /// 绑定树的数据源
        /// </summary>
        private async Task BindTree()
        {
            var pageDto = new DictTypePagedDto();
            var result = await BLLFactory<DictTypeService>.Instance.GetListAsync(pageDto);
            if (result != null)
            {
                this.tree.DataSource = result.Items;
                this.tree.ExpandAll();
            }
        }

而但我们单击某个字典大类的时候,应该列出对应大类下的字典项目,因此获取字典项目的数据操作如下所示。

/// <summary>
        /// 获取数据
        /// </summary>
        /// <returns></returns>
        private async Task<IPagedResult<DictDataInfo>> GetData(string dictType)
        {
            //构建分页的条件和查询条件
            var pagerDto = new DictDataPagedDto(this.winGridViewPager1.PagerInfo)
            {
                DictType_ID = dictType
            };
            var result = await BLLFactory<DictDataService>.Instance.GetListAsync(pagerDto);//new DictDataService().GetListAsync(pagerDto);
            return result;
        }

我们这里使用了分页查询的条件DictDataPagedDto,如果是需要获取全部,我们也可以通过调用GetAllAsync()函数来实现,如下导出全部的时候代码如下所示。

private async void winGridViewPager1_OnStartExport(object sender, EventArgs e)
        {
            if (this.winGridViewPager1.IsExportAllPage)
            {
                var result = await BLLFactory<DictDataService>.Instance.GetAllAsync();
                this.winGridViewPager1.AllToExport = result.Items;
            }
        }

这些处理都是基类预先定义好的API,我们通过子类强类型传入即可,非常方便,也简化很多代码。

同样,我们可以通过Get接口获取指定ID的实体信息,如下所示。

if (!string.IsNullOrEmpty(ID))
            {
                var info = await BLLFactory<DictDataService>.Instance.GetAsync(ID);
                if (info != null)
                {
                    this.txtName.Text = info.Name;
                    this.txtNote.Text = info.Remark;
                    this.txtSeq.Text = info.Seq;
                    this.txtValue.Text = info.Value;
                }
            }
if (!string.IsNullOrEmpty(ID))
            {
                var info = await BLLFactory<DictDataService>.Instance.GetAsync(ID);
                if (info != null)
                {
                    this.txtName.Text = info.Name;
                    this.txtNote.Text = info.Remark;
                    this.txtSeq.Text = info.Seq;
                    this.txtValue.Text = info.Value;
                }
            }

在Winform编辑界面中,我们重写保存更新的代码如下所示。

public override async Task<bool> SaveUpdated()
        {
            var info = await BLLFactory<DictDataService>.Instance.GetAsync(ID);
            if (info != null)
            {
                SetInfo(info);
                try
                {
                    return await BLLFactory<DictDataService>.Instance.UpdateAsync(info);
                }
                catch (Exception ex)
                {
                    LogTextHelper.Error(ex);
                    MessageDxUtil.ShowError(ex.Message);
                }
            }
            return false;
        }

以上是Winform界面中对常规数据处理接口的调用,这些都是通过强类型实体的方式调用基类函数,非常方便快捷,同时以提供了很好的API统一性实现。

最终界面效果和原先Winform开发框架一样功能。

 

 

专注于代码生成工具、.Net/.NetCore 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架等框架产品。
 转载请注明出处:撰写人:伍华聪  http://www.iqidi.com

相关文章
|
2月前
|
消息中间件 缓存 监控
优化微服务架构中的数据库访问:策略与最佳实践
在微服务架构中,数据库访问的效率直接影响到系统的性能和可扩展性。本文探讨了优化微服务架构中数据库访问的策略与最佳实践,包括数据分片、缓存策略、异步处理和服务间通信优化。通过具体的技术方案和实例分析,提供了一系列实用的建议,以帮助开发团队提升微服务系统的响应速度和稳定性。
|
2月前
|
消息中间件 缓存 监控
优化微服务架构中的数据库访问:策略与实践
随着微服务架构的普及,如何高效管理和优化数据库访问成为了关键挑战。本文探讨了在微服务环境中优化数据库访问的策略,包括数据库分片、缓存机制、异步处理等技术手段。通过深入分析实际案例和最佳实践,本文旨在为开发者提供实际可行的解决方案,以提升系统性能和可扩展性。
|
2月前
|
SQL NoSQL Java
彻底革新你的数据库操作体验!Micronaut数据访问技巧让你瞬间爱上代码编写!
【9月更文挑战第10天】Java开发者们一直在寻找简化应用程序与数据库交互的方法。Micronaut作为一个现代框架,提供了多种工具和特性来提升数据访问效率。本文介绍如何使用Micronaut简化数据库操作,并提供具体示例代码。Micronaut支持JPA/Hibernate、SQL及NoSQL(如MongoDB),简化配置并无缝集成。通过定义带有`@Repository`注解的接口,可以实现Spring Data风格的命名查询。
55 6
|
2月前
|
SQL 存储 关系型数据库
C#一分钟浅谈:使用 ADO.NET 进行数据库访问
【9月更文挑战第3天】在.NET开发中,与数据库交互至关重要。ADO.NET是Microsoft提供的用于访问关系型数据库的类库,包含连接数据库、执行SQL命令等功能。本文从基础入手,介绍如何使用ADO.NET进行数据库访问,并提供示例代码,同时讨论常见问题及其解决方案,如连接字符串错误、SQL注入风险和资源泄露等,帮助开发者更好地利用ADO.NET提升应用的安全性和稳定性。
178 6
|
2月前
|
SQL 关系型数据库 分布式数据库
PolarDB Proxy配置与优化:提升数据库访问效率
【9月更文挑战第6天】PolarDB是阿里云推出的高性能分布式关系型数据库,PolarDB Proxy作为其关键组件,位于客户端与PolarDB集群间,负责SQL请求的解析与转发,并支持连接池管理、SQL过滤及路由规则等功能。本文详细介绍了PolarDB Proxy的配置方法,包括连接池、负载均衡和SQL过滤设置,并探讨了监控调优、缓存及网络优化策略,以帮助提升数据库访问效率。
41 1
|
2月前
|
SQL 安全 Java
探索研究Servlet 数据库访问
【9月更文挑战第28天】
26 0
|
3月前
|
JSON 数据格式 Java
化繁为简的魔法:Struts 2 与 JSON 联手打造超流畅数据交换体验,让应用飞起来!
【8月更文挑战第31天】在现代 Web 开发中,JSON 成为数据交换的主流格式,以其轻量、易读和易解析的特点受到青睐。Struts 2 内置对 JSON 的支持,结合 Jackson 库可便捷实现数据传输。本文通过具体示例展示了如何在 Struts 2 中进行 JSON 数据的序列化与反序列化,并结合 AJAX 技术提升 Web 应用的响应速度和用户体验。
93 0
|
16天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
67 6
|
14天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
49 3
Mysql(4)—数据库索引
|
2天前
|
存储 关系型数据库 MySQL
MySQL vs. PostgreSQL:选择适合你的开源数据库
在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个。它们都有着强大的功能、广泛的社区支持和丰富的生态系统。然而,它们在设计理念、性能特点、功能特性等方面存在着显著的差异。本文将从这三个方面对MySQL和PostgreSQL进行比较,以帮助您选择更适合您需求的开源数据库。
14 4