开发框架Furion之Winform+SqlSugar

news2024/11/25 7:07:27

目录

1.开发环境

2.项目搭建

2.1 创建WinFrom主项目

2.2 创建子项目

2.3 实体类库基础类信息配置

2.3.1 Nuget包及项目引用

2.3.2 实体基类创建  

2.4 仓储业务类库基础配置

2.4.1 Nuget包及项目引用

2.4.2 Dtos实体

2.4.3 仓储基类

 2.5 service注册类库基础配置

2.5.1 config配置文件配置

2.5.2 Nuget包及项目引用

 2.5.4 SqlSugar数据库配置

2.5.5 service服务注册

2.6 主项目启动配置

 2.7 示例

2.7.1 codefirst 示例

 2.7.2仓储查询调用示例


1.开发环境

  • Visual studio 2022
  • SQLServer
  • .Net6

关于SqlSugar参见教程配置实体 - SqlSugar 5x - .NET果糖网

2.项目搭建

2.1 创建WinFrom主项目

Visual Studio 2022—创建新项目—项目模板中选择 Windows窗体应用

 

至此 项目初次创建完成 

 

 

2.2 创建子项目

分别创建项目名称为MyFurion.WFSqlsugar.Model(实体类库)、MyFurion.WFSqlsugar.Setup(service注册类库)、MyFurion.WFSqlsugar.Application(仓储业务类库)三个子项目

 

 

项目最终架构

 

2.3 实体类库基础类信息配置

2.3.1 Nuget包及项目引用

在MyFurion.WFSqlsugar.Model项目中添加SqlSugarCore

 

2.3.2 实体基类创建  

创建基类BaseEntity.cs类

using SqlSugar;
namespace MyFurion.WFSqlsugar.Model
{
    /// <summary>
    /// 实体基类
    /// </summary>
    [SugarIndex("index_{table}_id", nameof(Id), OrderByType.Asc, IsUnique = true)]
    [SugarIndex("index_{table}_createdate", nameof(CreateTime), OrderByType.Asc)]
    [SugarIndex("index_{table}_sort", nameof(SortNum), OrderByType.Asc)]
    [SugarIndex("index_{table}_del", nameof(IsDeleted), OrderByType.Asc)]
    [SugarIndex("index_{table}_orgid", nameof(CreateOrgId), OrderByType.Asc)]
    public class BaseEntity
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseEntity()
        {
            Id = SnowFlakeSingle.Instance.NextId();
            CreateTime = DateTime.Now;
            IsDeleted = true;
        }
        /// <summary>
        /// id
        /// </summary>
        [SugarColumn(IsPrimaryKey =true, ColumnDescription ="主键")]
        public long Id { get; set; }   
        /// <summary>
        /// 创建人id
        /// </summary>
        [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = true, ColumnDescription = "创建人id")]
        public string ?CreateUserId { get; set; }
        /// <summary>
        /// 创建人姓名
        /// </summary>
        [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = true, ColumnDescription = "创建人姓名")]
        public string? CreateUser { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = false, ColumnDescription = "创建时间")]
        public DateTime CreateTime { get; set; }
        /// <summary>
        /// 修改人id
        /// </summary>
        [SugarColumn(IsOnlyIgnoreInsert = true, IsNullable = true, ColumnDescription = "修改人id")]
        public string? ModifyUserId { get; set; }
        /// <summary>
        /// 修改人姓名
        /// </summary>
        [SugarColumn(IsOnlyIgnoreInsert = true, IsNullable = true, ColumnDescription = "修改人姓名")]
        public string? ModifyUser { get; set; }
        /// <summary>
        /// 修改时间
        /// </summary>
        [SugarColumn(IsOnlyIgnoreInsert =true, IsNullable = true, ColumnDescription = "修改时间")]
        public DateTime? ModifyTime { get; set; }
        /// <summary>
        /// 创建组织机构ID
        /// </summary>
        [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = true, ColumnDescription = "创建组织机构ID")]
        public string? CreateOrgId { get; set; }
        /// <summary>
        /// 创建组织机构名称
        /// </summary>
        [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = true, ColumnDescription = "创建组织机构名称")]
        public string? CreateOrgName { get; set; }
        /// <summary>
        /// 排序
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "排序")]
        public int SortNum { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "备注",ColumnDataType ="nvarchar(max)")]
        public string? Remark { get; set; }
        /// <summary>
        /// 是否删除
        /// </summary>
        [SugarColumn(ColumnDescription = "是否删除")]
        public bool IsDeleted { get; set; }
        /// <summary>
        /// 删除原因
        /// </summary>
        [SugarColumn(ColumnDescription = "删除原因", IsNullable = true)]
        public string? DeleteReason { get; set; }
        /// <summary>
        /// 删除时间
        /// </summary>
        [SugarColumn(IsOnlyIgnoreInsert = true, IsNullable = true, ColumnDescription = "删除时间")]
        public DateTime? DeleteTime { get; set; }
        /// <summary>
        /// 删除人
        /// </summary>
        [SugarColumn(ColumnDescription = "删除人", IsNullable = true)]
        public string? DeleteUser { get; set; }
        /// <summary>
        /// 删除单位
        /// </summary>
        [SugarColumn(ColumnDescription = "删除单位", IsNullable = true)]
        public string? DeleteOrg { get; set; }
        /// <summary>
        /// 多租户ID
        /// </summary>
        [SugarColumn(ColumnDescription = "多租户ID", DefaultValue = "0")]
        public long TenantId { get; set; } = 0;
    }
}

2.4 仓储业务类库基础配置

2.4.1 Nuget包及项目引用

在MyFurion.WFSqlsugar.Application项目中添加Furion、SqlSugar.IOC

添加对MyFurion.WFSqlsugar.Model项目的引用

 

 

2.4.2 Dtos实体

项目中创建Dtos文件,用于存放查询条件以及输出信息数据类

首先创建PageResult.cs和PageInputBase.cs,用于仓储基类中使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyFurion.WFSqlsugar.Application.Dtos
{
    /// <summary>
    /// 分页数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class PageResult<T>
    {
        /// <summary>
        /// 页码
        /// </summary>
        public int PageNo { get; set; }
        /// <summary>
        /// 分页大小
        /// </summary>
        public int PageSize { get; set; }
        /// <summary>
        /// 页总数
        /// </summary>
        public int TotalPage { get; set; }
        /// <summary>
        /// 数据总数
        /// </summary>
        public int TotalRows { get; set; }
        /// <summary>
        /// 记录集合
        /// </summary>
        public List<T> Rows { get; set; } = new();
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyFurion.WFSqlsugar.Application.Dtos
{
    public class PageInputBase
    {
        /// <summary>
        /// 搜索值
        /// </summary>
        public  string? SearchValue { get; set; }
        /// <summary>
        /// 当前页码
        /// </summary>
        public  int PageNo { get; set; } = 1;
        /// <summary>
        /// 页码容量
        /// </summary>
        public  int PageSize { get; set; } = 20;
        /// <summary>
        /// 搜索开始时间
        /// </summary>
        public string? SearchBeginTime { get; set; }
        /// <summary>
        /// 搜索结束时间
        /// </summary>
        public  string?SearchEndTime { get; set; }
    }
}

2.4.3 仓储基类

创建仓储基类BaseRepository.cs

using System.Reflection;
using System.Linq.Expressions;
using System.Data;
using MyFurion.WFSqlsugar.Model;
using MyFurion.WFSqlsugar.Application.Dtos;
using SqlSugar;
using SqlSugar.IOC;
using Furion.Logging;
namespace MyFurion.WFSqlsugar.Application
{
    public class BaseRepository<T> : SimpleClient<T> where T : BaseEntity, new()
    {
        public ITenant itenant = null;//多租户事务
        //private readonly ISqlSugarRepository repository;
        public BaseRepository(ISqlSugarClient context = null) : base(context)
        {
            //通过特性拿到ConfigId
            var configId = typeof(T).GetCustomAttribute<TenantAttribute>()?.configId;
            if (configId != null)
            {
                Context = DbScoped.SugarScope.GetConnectionScope(configId);//根据类传入的ConfigId自动选择
            }
            else
            {
                Context = context ?? DbScoped.SugarScope.GetConnectionScope(0);//没有默认db0
            }
            //Context = DbScoped.SugarScope.GetConnectionScopeWithAttr<T>();
            itenant = DbScoped.SugarScope;//设置租户接口
        }

        #region 基础业务
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> Add(T t)
        {
            try
            {
                int rowsAffect = await Context.Insertable(t).IgnoreColumns(true).ExecuteCommandAsync();
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"新增失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 批量新增
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> Insert(List<T> t)
        {
            try
            {
                int rowsAffect = await Context.Insertable(t).ExecuteCommandAsync();
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"批量新增失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 插入设置列数据
        /// </summary>
        /// <param name="parm"></param>
        /// <param name="iClumns"></param>
        /// <param name="ignoreNull"></param>
        /// <returns></returns>
        public async Task<bool> Insert(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true)
        {
            try
            {
                int rowsAffect = await Context.Insertable(parm).InsertColumns(iClumns).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommandAsync();
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"插入设置列数据失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="ignoreNullColumns"></param>
        /// <returns></returns>
        public async Task<bool> Update(T entity, bool ignoreNullColumns = false)
        {
            try
            {
                int rowsAffect = await Context.Updateable(entity).IgnoreColumns(ignoreNullColumns).ExecuteCommandAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"更新失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 根据实体类更新指定列 eg:Update(dept, it => new { it.Status });只更新Status列,条件是包含
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="expression"></param>
        /// <param name="ignoreAllNull"></param>
        /// <returns></returns>
        public async Task<bool> Update(T entity, Expression<Func<T, object>> expression, bool ignoreAllNull = false)
        {
            try
            {
                int rowsAffect = await Context.Updateable(entity).UpdateColumns(expression).IgnoreColumns(ignoreAllNull).ExecuteCommandAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"根据实体类更新指定列失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 根据实体类更新指定列 eg:Update(dept, it => new { it.Status }, f => depts.Contains(f.DeptId));只更新Status列,条件是包含
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="expression"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<bool> Update(T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where)
        {
            try
            {
                int rowsAffect = await Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommandAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"根据实体类更新指定列失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 更新指定列 eg:Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ UpdateTime = DateTime.Now, Title = "通知标题" });
        /// </summary>
        /// <param name="where"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns)
        {
            try
            {
                int rowsAffect = await Context.Updateable<T>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommandAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"更新指定列失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 事务 eg:var result = UseTran(() =>{SysRoleRepository.UpdateSysRole(sysRole);DeptService.DeleteRoleDeptByRoleId(sysRole.ID);DeptService.InsertRoleDepts(sysRole);});
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public bool UseTran(Action action)
        {
            try
            {
                var result = Context.Ado.UseTran(() => action());
                return result.IsSuccess;
            }
            catch (Exception ex)
            {
                Context.Ado.RollbackTran();
                Log.Error($"事务执行失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">主键id</param>
        /// <param name="IsDelete">是否真删除</param>
        /// <returns></returns>
        public async Task<bool> DeleteById(long id, bool IsDelete = false)
        {
            int rowsAffect = 0;
            try
            {
                if (IsDelete)
                {
                    rowsAffect = await Context.Deleteable<T>().In(id).ExecuteCommandAsync();
                }
                else
                {
                    //假删除 实体属性有isdelete或者isdeleted 请升级到5.0.4.9+,(5.0.4.3存在BUG)
                    rowsAffect = await Context.Deleteable<T>().In(id).IsLogic().ExecuteCommandAsync();
                }
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"删除失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 根据查询条件删除
        /// </summary>
        /// <param name="where"></param>
        /// <param name="IsDelete"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByWhere(Expression<Func<T, bool>> where, bool IsDelete = false)
        {
            int rowsAffect = 0;
            try
            {
                if (IsDelete)
                {
                    rowsAffect = await Context.Deleteable<T>().Where(where).ExecuteCommandAsync();
                }
                else
                {
                    //假删除 实体属性有isdelete或者isdeleted 请升级到5.0.4.9+,(5.0.4.3存在BUG)
                    rowsAffect = await Context.Deleteable<T>().Where(where).IsLogic().ExecuteCommandAsync();
                }
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"根据查询条件删除失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 根据id获取数据
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns>泛型实体</returns>
        public async Task<T> GetEntityById(long id)
        {
            return await Context.Queryable<T>().FirstAsync(p => p.Id == id);
        }
        /// <summary>
        /// 数据是否存在
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<bool> IsExists(Expression<Func<T, bool>> expression)
        {
            return await Context.Queryable<T>().Where(expression).AnyAsync();
        }
        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<T>> GetAll()
        {
            return await Context.Queryable<T>().ToListAsync();
        }
        /// <summary>
        /// 根据查询条件获取数据
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<List<T>> GetListByWhere(Expression<Func<T, bool>> expression)
        {
            return await Context.Queryable<T>().Where(expression).ToListAsync();
        }
        /// <summary>
        /// 根据查询条件获取数据(动态表格拼接查询条件)
        /// </summary>
        /// <param name="conditions"></param>
        /// <returns></returns>
        public async Task<List<T>> GetListByWhere(List<IConditionalModel> conditions)
        {
            return await Context.Queryable<T>().Where(conditions).ToListAsync();
        }
        /// <summary>
        /// 根据查询条件获取数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="orderFiled">排序字段</param>
        /// <param name="orderEnum">排序方式</param>
        /// <returns></returns>
        public async Task<List<T>> GetList(Expression<Func<T, bool>> expression, Expression<Func<T, object>> orderFiled, OrderByType orderEnum = OrderByType.Desc)
        {
            return await Context.Queryable<T>().Where(expression).OrderByIF(orderEnum == OrderByType.Asc, orderFiled, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, orderFiled, OrderByType.Desc).ToListAsync();
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public PageResult<T> GetPageList(Expression<Func<T, bool>> expression, int pageIndex, int pageSize)
        {
            int totalCount = 0;
            var result = Context.Queryable<T>().Where(expression).ToPageList(pageIndex, pageSize, ref totalCount);
            var pageResult = new PageResult<T>();
            pageResult.Rows = result;
            pageResult.TotalRows = totalCount;
            pageResult.TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize);
            return pageResult;
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<PageResult<T>> GetPageListAsync(Expression<Func<T, bool>> expression, int pageIndex, int pageSize)
        {
            RefAsync<int> totalCount = 0;
            var result = await Context.Queryable<T>().Where(expression).ToPageListAsync(pageIndex, pageSize, totalCount);
            var pageResult = new PageResult<T>();
            pageResult.Rows = result;
            pageResult.TotalRows = totalCount;
            pageResult.TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize);
            return pageResult;
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderFiled"></param>
        /// <param name="orderEnum"></param>
        /// <returns></returns>
        public PageResult<T> GetPageList(Expression<Func<T, bool>> expression, int pageIndex, int pageSize, Expression<Func<T, object>> orderFiled, OrderByType orderEnum = OrderByType.Desc)
        {
            int totalCount = 0;
            var result = Context.Queryable<T>().Where(expression).OrderByIF(orderEnum == OrderByType.Asc, orderFiled, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, orderFiled, OrderByType.Desc)
                .ToPageList(pageIndex, pageSize, ref totalCount);
            var pageResult = new PageResult<T>();
            pageResult.Rows = result;
            pageResult.TotalRows = totalCount;
            pageResult.TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize);
            return pageResult;
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderFiled"></param>
        /// <param name="orderEnum"></param>
        /// <returns></returns>
        public async Task<PageResult<T>> GetPageListAsync(Expression<Func<T, bool>> expression, int pageIndex, int pageSize, Expression<Func<T, object>> orderFiled, OrderByType orderEnum = OrderByType.Desc)
        {
            RefAsync<int> totalCount = 0;
            var result = await Context.Queryable<T>().Where(expression).OrderByIF(orderEnum == OrderByType.Asc, orderFiled, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, orderFiled, OrderByType.Desc)
                .ToPageListAsync(pageIndex, pageSize, totalCount);
            var pageResult = new PageResult<T>();
            pageResult.Rows = result;
            pageResult.TotalRows = totalCount;
            pageResult.TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize);
            return pageResult;
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderFiled"></param>
        /// <param name="orderEnum"></param>
        /// <returns></returns>
        public async Task<PageResult<T>> GetOffsetPageListAsync(Expression<Func<T, bool>> expression, int pageIndex, int pageSize, Expression<Func<T, object>> orderFiled, OrderByType orderEnum = OrderByType.Desc)
        {
            RefAsync<int> totalCount = 0;
            var result = await Context.Queryable<T>().Where(expression).OrderByIF(orderEnum == OrderByType.Asc, orderFiled, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, orderFiled, OrderByType.Desc)
                .ToOffsetPageAsync(pageIndex, pageSize, totalCount);
            var pageResult = new PageResult<T>();
            pageResult.Rows = result;
            pageResult.TotalRows = totalCount;
            pageResult.TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize);
            return pageResult;
        }
        #endregion

        #region 海量业务高性能
        /// <summary>
        /// 新增(对于海量数据并且性能要高的)
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> BulkAdd(T t)
        {
            try
            {
                int rowsAffect = await Context.Storageable(t).ToStorage().BulkCopyAsync();
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"新增失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 批量新增(对于海量数据并且性能要高的)
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> BatchBulkAdd(List<T> t)
        {
            try
            {
                int rowsAffect = await Context.Storageable(t).ToStorage().BulkCopyAsync();
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"批量新增失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 更新(对于海量数据并且性能要高的)
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<bool> BulkUpdate(T entity)
        {
            try
            {
                int rowsAffect = await Context.Storageable(entity).ToStorage().BulkUpdateAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"更新失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 批量更新(对于海量数据并且性能要高的)
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> BatchBulkUpdate(List<T> t)
        {
            try
            {
                Context.QueryFilter = new QueryFilterProvider();//清空过滤器 否则会出现Parameter '@IsDelete0' must be defined错误
                int rowsAffect = await Context.Storageable(t).ToStorage().BulkUpdateAsync();
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"更新失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 批量更新(对于海量数据并且性能要高的)
        /// </summary>
        /// <param name="t"></param>
        /// <param name="updateColumns"></param>
        /// <returns></returns>
        public async Task<bool> BatchBulkUpdate(List<T> t, string[] updateColumns)
        {
            try
            {
                Context.QueryFilter = new QueryFilterProvider();//清空过滤器 否则会出现Parameter '@IsDelete0' must be defined错误
                int rowsAffect = await Context.Storageable(t).ToStorage().BulkUpdateAsync(updateColumns);
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"更新失败:{ex.Message}");
                return false;
            }
        }
        #endregion

        #region 存储过程
        /// <summary>
        /// 存储过程
        /// </summary>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<DataTable> ProcedureQuery(string procedureName, object parameters)
        {
            return await Context.Ado.UseStoredProcedure().GetDataTableAsync(procedureName, parameters);
        }
        /// <summary>
        /// 存储过程
        /// </summary>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public async Task<List<T>> ProcedureQueryList(string procedureName, object parameters)
        {
            return await Context.Ado.UseStoredProcedure().SqlQueryAsync<T>(procedureName, parameters);
        }
        #endregion

        #region Fastest
        /// <summary>
        /// 批量新增
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> BatchFastestkAdd(List<T> t)
        {
            try
            {
                int rowsAffect = await Context.Fastest<T>().BulkCopyAsync(t);
                return rowsAffect > 0;
            }
            catch (Exception ex)
            {
                Log.Error($"fastest批量新增失败:{ex.Message}");
                return false;
            }
        }
        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> BatchFastestUpdate(List<T> t)
        {
            try
            {
                Context.QueryFilter = new QueryFilterProvider();//清空过滤器 否则会出现Parameter '@IsDelete0' must be defined错误
                int rowsAffect = await Context.Fastest<T>().BulkUpdateAsync(t);
                return rowsAffect >= 0;
            }
            catch (Exception ex)
            {
                Log.Error($"fastest批量更新失败:{ex.Message}");
                return false;
            }
        }
        #endregion
    }
}

 2.5 service注册类库基础配置

2.5.1 config配置文件配置

 首先在主项目MyFurion.WFSqlSugar中新增App.config配置文件,并配置数据库连接配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appSettings>
		<!--数据库连接-->
		<add key="SqlserverConn" value="Data Source=.;User ID=sa;Password=123456;Initial Catalog=MyFurionTest"/>
		<!--是否需要codeFirst模式-->
		<add key="IsCodeFirst" value="1"/>
	</appSettings>
</configuration>

2.5.2 Nuget包及项目引用

在项目MyFurion.WFSqlsugar.Setup中添加对项目MyFurion.WFSqlsugar.Application的引用

添加Furion.Extras.DatabaseAccessor.SqlSugar、System.Configuration.ConfigurationManager、System.Linq.Dynamic.Core

 

 

 2.5.4 SqlSugar数据库配置

 创建SqlSugarSet.cs文件,用于对SqlSugar数据库连接的配置数据

using System.Linq.Expressions;
using System.Linq.Dynamic.Core;
using System.Reflection;
using MyFurion.WFSqlsugar.Model;
using SqlSugar;
using SqlSugar.IOC;
using Furion.Logging;
namespace MyFurion.WFSqlsugar.Setup
{
    /// <summary>
    /// 数据库配置
    /// </summary>
    public class SqlSugarSet
    {
        public static void AddSqlsugarSetup()
        {
            string sqlserverConn = System.Configuration.ConfigurationManager.AppSettings["SqlserverConn"].ToString();
            string isCodefirst= System.Configuration.ConfigurationManager.AppSettings["IsCodeFirst"].ToString();
            //string orcaleConn = System.Configuration.ConfigurationManager.AppSettings["OrcaleConn"].ToString();
            List<IocConfig> iocConfigs = new List<IocConfig>()
            {
                new IocConfig (){ ConnectionString=sqlserverConn,ConfigId=0,IsAutoCloseConnection=true,DbType=IocDbType.SqlServer},
                //new IocConfig (){ ConnectionString=orcaleConn,ConfigId=1,IsAutoCloseConnection=true,DbType=IocDbType.Oracle}
            };
            SugarIocServices.AddSqlSugar(iocConfigs);
            SugarIocServices.ConfigurationSugar(db =>
            {
                foreach (var iocItem in iocConfigs)
                {
                    SqlSugarProvider dbClient = db.GetConnection(iocItem.ConfigId);
                    SetQueryFilter(dbClient);
                    //sql执行语句日志
                    dbClient.Aop.OnLogExecuting = (sql, pars) =>
                    {
                        try
                        {
                            Log.Information(SqlProfiler.ParameterFormat(sql, pars));
                        }
                        catch (Exception ex)
                        {
                            Log.Error($"日志错误{ex.StackTrace}");
                        }
                    };
                }
            });
            if (isCodefirst == "1")
            {
                CreateTable(iocConfigs);
            }
        }
        /// <summary>
        /// 创建数据库表 codefirst
        /// </summary>
        private static void CreateTable(List<IocConfig> iocConfigs)
        {
            foreach (var item in iocConfigs)
            {
                string configId = item.ConfigId;
                ISqlSugarClient db = DbScoped.SugarScope.GetConnectionScope(configId);
                db.DbMaintenance.CreateDatabase();//没有数据库的时候创建数据库
                var tableLists = db.DbMaintenance.GetTableInfoList();
                var files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyFurion.WFSqlsugar.Model.dll");
                if (files.Length > 0)
                {
                    Type[] types = Assembly.LoadFrom(files[0]).GetTypes().Where(it => it.BaseType == typeof(BaseEntity)).ToArray();
                    //Type[] types = Assembly.LoadFrom(files[0]).GetTypes().ToArray();
                    foreach (var entityType in types)
                    {
                        //创建数据表
                        string tableName = entityType.GetCustomAttribute<SugarTable>().TableName.ToLower();//根据特性获取表名称
                        var configid = entityType.GetCustomAttribute<TenantAttribute>()?.configId;//根据特性获取租户id
                        configid = configid == null ? "0" : configid.ToString();
                        if (!tableLists.Any(p => p.Name == tableName) && configId == configid.ToString())
                        {
                            //创建数据表包括字段更新
                            db.CodeFirst.InitTables(entityType);
                        }
                    }
                    db.Close();
                }
            }
        }
        /// <summary>
        /// 添加全局过滤器
        /// </summary>
        /// <param name="provider"></param>
        private static void SetQueryFilter(SqlSugarProvider provider)
        {
            //添加全局过滤器
            var files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyFurion.WFSqlsugar.Model.dll");
            if (files.Length > 0)
            {
                Type[] types = Assembly.LoadFrom(files[0]).GetTypes().Where(it => it.BaseType == typeof(BaseEntity)).ToArray();
                foreach (var entityType in types)
                {
                    //string tableName = entityType.GetCustomAttribute<SugarTable>().TableName;//根据特性获取表名称
                    var lambda =DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(entityType, "it") },
                        typeof(bool), $"{nameof(BaseEntity.IsDeleted)} ==  @0",false);
                    provider.QueryFilter.Add(new TableFilterItem<object>(entityType, lambda, true)); //将Lambda传入过滤器
                }
            }
            //插入/更新过滤器,用于审计日志
            provider.Aop.DataExecuting = (oldValue, entityInfo) =>
            {
                //新增时操作
                if (entityInfo.OperationType == DataFilterType.InsertByObject)
                {

                }
                //修改时操作        
                if (entityInfo.OperationType == DataFilterType.UpdateByObject)
                {
                    if (entityInfo.PropertyName == "ModifyTime")
                    {
                        entityInfo.SetValue(DateTimeOffset.Now);//修改UpdateTime字段
                    }
                }
            };
        }
    }
}

2.5.5 service服务注册

创建YourStartup.cs,用于Furion框架的相关service的服务注册

using Furion;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace MyFurion.WFSqlsugar.Setup
{
    public class YourStartup : AppStartup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddRemoteRequest();
            services.AddDatabaseAccessor();//使用数据库配置
            services.AddLogging();//日志服务
            //设置日志
            System.Array.ForEach(new[] { LogLevel.Information, LogLevel.Error }, logLevel =>
            {
                services.AddFileLogging("Logs/{1}-{0:yyyy}-{0:MM}-{0:dd}-{0:HH}.log", options =>
                {
                    options.FileNameRule = fileName => string.Format(fileName, System.DateTime.UtcNow, logLevel.ToString());
                    options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;
                    options.Append = true;
                    //options.MessageFormat = (logMsg) =>
                    //{
                    //    var stringBuilder = new System.Text.StringBuilder();
                    //    stringBuilder.Append(System.DateTime.Now.ToString("o"));
                    //    // 其他的。。。自己组装
                    //    return stringBuilder.ToString();
                    //};
                });
            });
            SqlSugarSet.AddSqlsugarSetup();
        }
    }
}

2.6 主项目启动配置

在项目MyFurion.WFSqlSugar添加对项目MyFurion.WFSqlsugar.Setup的引用

Program.cs中添加代码

 Serve.RunNative(includeWeb: false);//furion框架配置,默认启动

 2.7 示例

2.7.1 codefirst 示例

创建SystemUser.cs实体类,配置相关表名及租户id

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;

namespace MyFurion.WFSqlsugar.Model
{
    [SugarTable("Sys_User")]
    [Tenant("0")]
    public class SystemUser:BaseEntity
    {
        /// <summary>
        /// 账号
        /// </summary>
        [SugarColumn(Length = 50, ColumnDescription = "账号")]
        public string Account { get; set; }
        /// <summary>
        /// 密码(默认MD5加密)
        /// </summary>
        [SugarColumn(Length = 50, ColumnDescription = "密码")]
        public string Password { get; set; }
        /// <summary>
        /// 昵称
        /// </summary>
        [SugarColumn(Length = 20, IsNullable = true, ColumnDescription = "昵称")]
        public string NickName { get; set; }
        /// <summary>
        /// 姓名
        /// </summary>
        [SugarColumn(Length = 20, IsNullable = true, ColumnDescription = "姓名")]
        public string UserName { get; set; }
    }
}

启动项目,自动创建数据表,效果展示

 2.7.2仓储查询调用示例

用户仓储

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Furion.DependencyInjection;
using MyFurion.WFSqlsugar.Model;
using MyFurion.WFSqlsugar.Application.Dtos;
using SqlSugar;
using System.Linq.Expressions;

namespace MyFurion.WFSqlsugar.Application
{
    /// <summary>
    /// 用户仓储业务
    /// </summary>
    public class UserRepository : BaseRepository<SystemUser>, ITransient
    {
        /// <summary>
        /// 账户是否已存在
        /// </summary>
        /// <param name="account"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> IsExists(string account, long id)
        {
            return await Context.Queryable<SystemUser>().AnyAsync(x => x.Account == account && x.Id != id);
        }
        /// <summary>
        /// 分页数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageResult<SystemUser>> GetPageList(PageInputBase input)
        {
            var exp = Expressionable.Create<SystemUser>();
            exp.AndIF(!string.IsNullOrWhiteSpace(input.SearchValue), it => it.UserName.Contains(input.SearchValue)||it.Account.Contains(input.SearchValue));
            Expression<Func<SystemUser, dynamic>> sortPredicate = x => x.CreateTime;
            return await GetPageListAsync(exp.ToExpression(),input.PageNo,input.PageSize, sortPredicate);
        }
    }
}

form页面调用查询

 

using Furion;
using MyFurion.WFSqlsugar.Application;
using MyFurion.WFSqlsugar.Application.Dtos;
using MyFurion.WFSqlsugar.Model;

namespace MyFurion.WFSqlSugar
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
           UserRepository userRepository= App.GetService<UserRepository>();
           var data = userRepository.GetPageList(new PageInputBase() { PageNo=1,PageSize=20}).Result;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图形数据库】Neo4j简介及应用场景

文章目录 1.什么是Neo4j?2.图形数据结构3.Neo4j应用场景3.1我们可以将图领域划分成以下两部分&#xff1a;3.2目前&#xff0c;业内已经有了相对比较成熟的基于图数据库的解决方案&#xff0c;大致可以分为以下几类。3.2.1金融行业应用3.2.2社交网络图谱3.2.3企业关系图谱 总结…

Linux进程通信:存储映射mmap

1. 存储映射是什么&#xff1f; 如上图&#xff0c;存储映射是将块设备的文件映射到进程的虚拟地址空间。之后&#xff0c;进程可以直接使用指针操作其地址空间中映射的文件&#xff0c;对这块映射区操作就相当于操作文件。 2. 存储映射函数mmap的简单使用 &#xff08;1&…

网络安全岗位面试题大全:解析各个分支岗位的面试题目,帮助你上岸大厂

网络安全是一个广泛的领域&#xff0c;涵盖了许多不同的岗位和分支。我整理了网络安全各个岗位分支的面试题目&#xff1a; 安全工程师/系统管理员 您如何确保网络系统的安全性和保密性&#xff1f;您采用了哪些技术和工具&#xff1f;请描述一下您在过去工作中遇到的最具挑战…

C++ -5- 内存管理

文章目录 C语言和C内存管理的区别示例1. C/C 中程序内存区域划分2. C中动态内存管理3.operator new 与 operator delete 函数4.new 和 delete 的实现原理5.定位new表达式 C语言和C内存管理的区别示例 //C语言&#xff1a; struct SListNode {int data;struct SListNode* next; …

什么是内存?什么是内存逃逸?怎么做内存逃逸分析

内存 平时我们在电脑上听歌&#xff0c;聊天&#xff0c;或者启动某个程序&#xff0c;那么这个启动过程&#xff0c;其实就是把程序从硬盘读入到内存中去。就像安卓手机&#xff0c;内存不够了很卡&#xff0c;杀掉几个软件&#xff0c;内存就升上来了。但也不是所有的程序都…

产品经理需要了解api接口的哪些东西

一、作为产品经理&#xff0c;需要了解API接口的以下方面&#xff1a; 功能&#xff1a;API接口的功能是指它提供的业务功能&#xff0c;包括数据查询、修改、增加、删除、计算等等&#xff0c;根据产品的需求确定需要调用哪些API接口。请求方式和传参&#xff1a;API接口的请…

致力提供一站式数据可视化解决方案,支持报表、图表、大屏

一、开源项目简介 Davinci是一个DVAAS&#xff08;Data Visualization as a Service&#xff09;平台解决方案。 Davinci面向业务人员/数据工程师/数据分析师/数据科学家&#xff0c;致力于提供一站式数据可视化解决方案。既可作为公有云/私有云独立使用&#xff0c;也可作为…

Linux进程通信:信号

1. 信号的概念 Linux进程间通信的方式之一。信号也称为“软件中断”。 信号特点&#xff1a; 简单&#xff1b;携带信息有限&#xff1b;满足特定条件才发送信号&#xff1b;可进行用户空间和内核空间进程的交互&#xff1b; 2. 信号的编号 kill -l // 查看信号编号 POS…

ModelArts的使用

完整流程第一个实例&#xff1a;AI初学者&#xff1a;使用订阅算法构建模型实现花卉识别_AI开发平台ModelArts_最佳实践_模型训练&#xff08;预置算法-新版训练&#xff09;_华为云 一、支持的模型 可以在gitee上下载标准网络模型&#xff1a; models: Models of MindSpore …

Prometheus优化及高可用

Prometheus优化及高可用 概述 Prometheus几乎已成为监控领域的事实标准&#xff0c;它自带高效的时序数据库存储&#xff0c;可以让单台 Prometheus 能够高效的处理大量的数据&#xff0c;还有友好并且强大的 PromQL 语法&#xff0c;可以用来灵活的查询各种监控数据以及配置…

使用 chat_flutter 进行聊天记录展示

前言 最近需要实现一个聊天记录的页面展示&#xff0c;在网上发现没有适合自己的&#xff0c;于是自己就造了一个&#xff0c;总体感觉还不赖。 下面奉上地址、效果图和教程。 效果图 地址 github: https://github.com/xiaorui-23/chat_fluttergitee: https://gitee.com/xi…

搭建微型服务器(node express框架)

目录 一&#xff1a;打包&#xff08;npm run build&#xff09; 二&#xff1a;变成合法的包&#xff08;新建server文件夹&#xff09; 三&#xff1a;一路回车 四&#xff1a;新建服务器主文件 五&#xff1a;编辑server.js 六&#xff1a;node server启动服务器 七&a…

第十二章 享元模式

文章目录 前言一、享元模式基本介绍二、享元模式解决网站展现项目完整代码WebSite 抽象网站类User 外部状态用户内部状态网站 ConcreteWebSite网站工厂产生网站和负责共享&#xff08;池&#xff09; WebSiteFactoryClint 测试 三、享元模式在JDK-Interger的应用源码分析四、享…

NFS部署

共享/webdata/目录&#xff1b; ~ 用于存储 AppSrv 主机的 WEB 数据&#xff1b; ~ 仅允许 AppSrv 主机访问该共享&#xff1b; ~ 考虑安全&#xff0c;不论登入 NFS 的使用者身份为何&#xff0c;都将其设置为匿名用 户访问 StorageSrv和AppSrv nfs共享 1.安装nfs(App…

pdf怎么删除其中一页?

pdf怎么删除其中一页&#xff1f;大家都应该知道&#xff0c;PDF是一种实用性非常强且非常便携文件格式&#xff0c;许多用户对其非常熟悉。不管是工作还是学习中&#xff0c;都会下载或者使用到pdf文件。pdf文件具有非常好的兼容性&#xff0c;F可以将各种图片、文字内容整合在…

根据cadence设计图学习硬件知识day05 了解一些芯片

1.NXS0102DC &#xff08;2位双电源转换收发器&#xff09; 1.NXS0102DC 介绍 NXS0102是一款2位双电源转换收发器&#xff0c;具有自动方向感测功能&#xff0c;可实现双向电压电平转换。它具有两个2位输入输出端口&#xff08;An和Bn&#xff09;、一个输出使能输入&#xf…

Transformer 原理及代码详细解析

Transformer 原理及代码详细解析 文章目录 Transformer 原理及代码详细解析一、Transformer 背景介绍1.1 Transformer 的诞生1.2 Transformer 的优势1.3 Transformer 的市场 二、Transformer架构解析2.1 认识 Transformer 架构2.1.1 Transformer模型的作用2.1.2 Transformer 总…

k8s优雅终止pod

k8s优雅终止pod 概述 Pod 销毁时&#xff0c;会停止容器内的进程&#xff0c;通常在停止的过程中我们需要执行一些善后逻辑&#xff0c;比如等待存量请求处理完以避免连接中断&#xff0c;或通知相关依赖进行清理等&#xff0c;从而实现优雅终止目的。本文介绍在 Kubernetes …

深度学习—入门

深度学习与机器学习的区别 深度学习由机器学习中的神经网络发展而来&#xff0c;机器学习多用于处理数值数据&#xff0c;而深度学习还可处理图片、音频等数据。 特征提取方面 机器学习的特征工程步骤需要靠手动完成&#xff0c;需要大量专业领域知识。深度学习通常由多个层组…

Mysql8.0 包学包会!一篇文章解决Mysql

基于尚硅谷的Mysql8.0视频&#xff0c;修修改改。提取了一些精炼的内容。 首先需要在数据库内引入一张表。链接地址如下。 链接&#xff1a;https://pan.baidu.com/s/1DD83on3J1a2INI7vrqPe4A 提取码&#xff1a;68jy 会进行持续更新。。 1. Mysql目录结构 Mysql的目录结构…