草庐IT

猿创征文|【国产数据库】一文学会应用SqlSugar工作单元模式操作多数据库

会敲键盘的肘子 2023-06-10 原文

🐋作者简介:博主是一位.Net开发者,同时也是RPA和低代码平台的践行者。
🐬个人主页:会敲键盘的肘子
🐰系列专栏:SqlSugar ORM
🦀专栏简介:SqlSugar是一款来自未来的ORM,拥有超前的理念,需求领跑第一线,在设计理念上就算不更新几年都不会过时,是一款真正用了功能齐全的ORM框架。博主在工作中学习和实战SqlSugar,形成本专栏,希望可以帮助到您解决问题。
🐶座右铭:总有一天你所坚持的会反过来拥抱你。


📖 前言

​ 随着华为、中兴事务,国产数据库市场相信是未来是趋势走向,纵观 .net core 整个圈子FreeSqlSqlSugar(排名不分先后)都已早早支持国产数据库,比如人大金仓、神通、达梦,针对不同的项目要求支持适配不同的国产数据库。今天我们使用 SqlSugar ORM 的工作单元模式来连接多个国产数据库

SqlSugar是一款来自未来的ORM开箱即用,拥有超前的理念,需求领跑第一线,在设计理念上就算不更新几年都不会过时,是一款真正用了功能齐全的ORM框架。

感谢果糖大数据科技团队对SqlSugar的维护和更新。


👉本文关键字:国产数据库、SqlSugar、ORM、人大金仓、达梦、翰高

文章目录

📑 Sqlsugar基本介绍

♈ 基本介绍

​ SqlSugar 是一款 老牌 .NET 开源ORM框架,由果糖大数据科技团队维护和更新 ,开箱即用最易上手的ORM框架 ,51Job和Boss直招简历数超过 国外框架 Nhibernate PetaPoco, 仅次于Dapper和EF Core , 占Dapper 40% 。

⭐ 功能介绍

  1. 相比EF Core【学习成本低一天学会】,多库支持更好 ,在国内拥有不逊色EF Core 的【开源生态】。
  2. 支持 .NET 百万级【大数据】写入和更新、分表和几十亿查询和统计等 拥有成熟方案。
  3. 支持 完整的SAAS一套应用 跨库查询 、租户分库 、租户分表 和 租户数据隔离。
  4. 支持【低代码】+工作流 (无实体多库兼容CRUD & JSON TO SQL )。
  5. 语法最爽的ORM、优美的表达式、仓储、UnitOfWork、DbContext、AOP。
  6. 支持 DbFirst、CodeFirst和【WebFirst】 3种模式开发。
  7. 简单易用、功能齐全、高性能、轻量级、服务齐全、官网教程文档、有专业技术支持一天18小时服务。

⭐ 数据库支持

关系型数据库MySql、SqlServer、Sqlite、Oracle 、 postgresql、达梦、人大金仓、神通数据库、瀚高、Access 、MySqlConnector、华为 GaussDB 、南大通用 GBase 、Odbc、自定义
时序数据库QuestDb (适合几十亿数据分析,模糊查询,自动分表存储 ,缺点不支持删除)
列式存储库Clickhouse(适用于商业智能领域(BI),缺点大小写必须和库一样,不支持事务)
即将上线Mongodb(mongodb.entities)TDengine、Sybase…

♉ Nuget安装

⭐ 打开Nuget

​ 点击项目引用 >> 右键 Nuget管理

⭐ 安装SqlSugar

​ .Net Core 3 & 5 & 6 &7

⭐ SqlSugar源码

​ 博主这里因为需要对SqlSugar做一些修改,所以用了源码,结构如下,

📑 工作单元模式/IUnitOfWorK

♊ 工作单元模式/IUnitOfWorK

⭐ 数据库枚举

public enum DbType
{
    MySql ,
    SqlServer,
    Sqlite,
    Oracle,
    PostgreSQL,
    Dm, 
    Kdbndp // 人大金仓 只支持.NET CORE
}

⭐ 连接字符串(多数据库)

appsettings.json配置

"ConnectionStrings": {
    "kdbndp": "data source=127.0.0.1;database=test;Port=54321;UID=SYSTEM;PWD=system", //测试版本用人大金仓数据库
    "Oracledb": "data source=127.0.0.1/mes;user id=mes_open;password=123456", //Oracle数据库
    "MySqldb": "data source=127.0.0.1;database=production;uid=root;pwd=123456",//MySql数据库
    "DMdb":"PORT=5236;DATABASE=DAMENG;HOST=127.0.0.1;PASSWORD=SYSDBA;USER ID=SYSDBA",//DM数据库
    "HGdb":"PORT=5432;DATABASE=SqlSugar4xTest;HOST=localhost;PASSWORD=haosql;USER ID=postgres",//瀚高数据库
  },

♉ 实现

⭐ UnitOfWork.cs 工作单元实现

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using SqlSugar;
using System;

namespace Sys.Infrastructure.Data
{
    /// <summary>
    /// 工作单元实现
    /// </summary>
    public abstract class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork(IConfiguration configuration, IHttpContextAccessor accessor)
        {
            Configuration = configuration;
            HttpContextAccessor = accessor;
        }

        protected IConfiguration Configuration { get; set; }
        public IHttpContextAccessor HttpContextAccessor { get; set; }
        protected DateTime StartTime { get; set; }
        protected DateTime EndTime { get; set; }

        public SqlSugarClient Db { get; protected set; }

        public void BeginTran() => Db.BeginTran();

        public void CommitTran()
        {
            try
            {
                Db.CommitTran();
            }
            catch (Exception ex)
            {
                Db.RollbackTran();
                throw ex;
            }
        }

        public void RollbackTran() => Db.RollbackTran();
    }
}

⭐ KdbndpOfWork.cs(人大金仓数据库)

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System;
using System.IO;
using System.Linq;


namespace Sys.Infrastructure.Data
{
    public class KdbndpOfWork : UnitOfWork, IUnitOfWork
    {
        public KdbndpOfWork(IConfiguration configuration, IHttpContextAccessor accessor) : base(configuration, accessor)
        {
            Db = new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = configuration.GetConnectionString("kdbndpdb"), //数据库连接在 appsettings.json 中配置
                DbType = DbType.Kdbndp,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuted = OnLogExecuted,
                    OnLogExecuting = OnLogExecuting,
                    OnError = OnError
                }
            });
        }

        /// <summary>
        /// 当数据库操作执行出错时
        /// </summary>
        /// <param name="exception"></param>
        private static void OnError(SqlSugarException exception)
        {

        }

        /// <summary>
        /// 当数据库操作执行时
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuting(string sql, SugarParameter[] parameters)
        {
            //StartTime = DateTime.Now;
        }

        /// <summary>
        /// 当数据库操作执行完毕后
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuted(string sql, SugarParameter[] parameters)
        {
           // EndTime = DateTime.Now;
            
            //CreateHttpSqlLog(sql, parameters);
        }

       
    }
}

⭐ DMOfWork.cs(达梦数据库)

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System;
using System.IO;
using System.Linq;


namespace Sys.Infrastructure.Data
{
    public class DMOfWork : UnitOfWork, IUnitOfWork
    {
        public DMOfWork(IConfiguration configuration, IHttpContextAccessor accessor) : base(configuration, accessor)
        {
            Db = new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = configuration.GetConnectionString("DMdb"), //数据库连接在 appsettings.json 中配置
                DbType = DbType.DM,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuted = OnLogExecuted,
                    OnLogExecuting = OnLogExecuting,
                    OnError = OnError
                }
            });
        }

        /// <summary>
        /// 当数据库操作执行出错时
        /// </summary>
        /// <param name="exception"></param>
        private static void OnError(SqlSugarException exception)
        {

        }

        /// <summary>
        /// 当数据库操作执行时
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuting(string sql, SugarParameter[] parameters)
        {
            //StartTime = DateTime.Now;
        }

        /// <summary>
        /// 当数据库操作执行完毕后
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuted(string sql, SugarParameter[] parameters)
        {
           // EndTime = DateTime.Now;
            
            //CreateHttpSqlLog(sql, parameters);
        }

       
    }
}

⭐ MysqlOfWork.cs(MySQL数据库)

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using Supcon.APS.Common;
using Supcon.APS.Domain.Core;
using Supcon.APS.Domain.Entities;
using Supcon.APS.Domain.Entities.Sys;
using Supcon.APS.Domain.IRepository;
using System;
using System.IO;
using System.Linq;


namespace Sys.Infrastructure.Data
{
    public class MysqlOfWork : UnitOfWork, IUnitOfWork
    {
        public MysqlOfWork(IConfiguration configuration, IHttpContextAccessor accessor) : base(configuration, accessor)
        {
            Db = new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = configuration.GetConnectionString("Mysqldb"), //数据库连接在 appsettings.json 中配置
                DbType = DbType.MySQL,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuted = OnLogExecuted,
                    OnLogExecuting = OnLogExecuting,
                    OnError = OnError
                }
            });
        }

        /// <summary>
        /// 当数据库操作执行出错时
        /// </summary>
        /// <param name="exception"></param>
        private static void OnError(SqlSugarException exception)
        {

        }

        /// <summary>
        /// 当数据库操作执行时
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuting(string sql, SugarParameter[] parameters)
        {
            //StartTime = DateTime.Now;
        }

        /// <summary>
        /// 当数据库操作执行完毕后
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuted(string sql, SugarParameter[] parameters)
        {
           // EndTime = DateTime.Now;
            
            //CreateHttpSqlLog(sql, parameters);
        }

       
    }
}

⭐ OracleOfWork.cs(Oracle数据库)

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using Supcon.APS.Common;
using Supcon.APS.Domain.Core;
using Supcon.APS.Domain.Entities;
using Supcon.APS.Domain.Entities.Sys;
using Supcon.APS.Domain.IRepository;
using System;
using System.IO;
using System.Linq;


namespace Sys.Infrastructure.Data
{
    public class OracleOfWork : UnitOfWork, IUnitOfWork
    {
        public OracleOfWork(IConfiguration configuration, IHttpContextAccessor accessor) : base(configuration, accessor)
        {
            Db = new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = configuration.GetConnectionString("Oracledb"), //数据库连接在 appsettings.json 中配置
                DbType = DbType.Oracle,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuted = OnLogExecuted,
                    OnLogExecuting = OnLogExecuting,
                    OnError = OnError
                }
            });
        }

        /// <summary>
        /// 当数据库操作执行出错时
        /// </summary>
        /// <param name="exception"></param>
        private static void OnError(SqlSugarException exception)
        {

        }

        /// <summary>
        /// 当数据库操作执行时
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuting(string sql, SugarParameter[] parameters)
        {
            //StartTime = DateTime.Now;
        }

        /// <summary>
        /// 当数据库操作执行完毕后
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuted(string sql, SugarParameter[] parameters)
        {
           // EndTime = DateTime.Now;
            
            //CreateHttpSqlLog(sql, parameters);
        }

       
    }
}

⭐ HGdbOfWork.cs(瀚高数据库)

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using Supcon.APS.Common;
using Supcon.APS.Domain.Core;
using Supcon.APS.Domain.Entities;
using Supcon.APS.Domain.Entities.Sys;
using Supcon.APS.Domain.IRepository;
using System;
using System.IO;
using System.Linq;


namespace Sys.Infrastructure.Data
{
    public class HGdbOfWork : UnitOfWork, IUnitOfWork
    {
        public HGdbOfWork(IConfiguration configuration, IHttpContextAccessor accessor) : base(configuration, accessor)
        {
            Db = new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = configuration.GetConnectionString("HGdb"), //数据库连接在 appsettings.json 中配置
                DbType = SqlSugar.DbType.PostgreSQL,
    			IsAutoCloseConnection = true,
    			MoreSettings=new ConnMoreSettings() {
       				 PgSqlIsAutoToLower=false //数据库存在大写字段的 ,需要把这个设为false ,并且实体和字段名称要一样
    			},
    			AopEvents = new AopEvents
    			{
        			OnLogExecuting = (sql, p) =>
        			{
            			Console.WriteLine(sql);
            			Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
        			}
    			}
            });
        }

        /// <summary>
        /// 当数据库操作执行出错时
        /// </summary>
        /// <param name="exception"></param>
        private static void OnError(SqlSugarException exception)
        {

        }

        /// <summary>
        /// 当数据库操作执行时
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuting(string sql, SugarParameter[] parameters)
        {
            //StartTime = DateTime.Now;
        }

        /// <summary>
        /// 当数据库操作执行完毕后
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        private static void OnLogExecuted(string sql, SugarParameter[] parameters)
        {
           // EndTime = DateTime.Now;
            
            //CreateHttpSqlLog(sql, parameters);
        }

       
    }
}

📑 仓储

♊ 定义

仓储有一套自带的数据库操作方法,比起 db.xx.xxx来说可能更简便些满足一些常用需求, 复杂的功能还是用db.xxx.xxx。

⭐ 仓储接口

public interface IRepository<TEntity> : IRepository<Guid, TEntity, IUnitOfWork>
            where TEntity : ApsEntity, new()
    {

    }

/// <summary>
/// 人大金仓仓储接口
/// </summary>
public interface IKdbndpRepository<TEntity> : IRepository<int, TEntity, IUnitOfWork>
        where TEntity : SupplyChanEntity, new()
    {

    }


/// <summary>
///达梦仓储接口
/// </summary>
public interface IDMRepository<TEntity> : IRepository<int, TEntity, IUnitOfWork>
        where TEntity : SupplyChanEntity, new()
    {

    }


/// <summary>
/// 翰高仓储接口
/// </summary>
public interface IHGRepository<TEntity> : IRepository<int, TEntity, IUnitOfWork>
        where TEntity : SupplyChanEntity, new()
    {

    }

/// <summary>
/// MySQL仓储接口
/// </summary>
public interface IMySQLRepository<TEntity> : IRepository<int, TEntity, IUnitOfWork>
        where TEntity : SupplyChanEntity, new()
    {

    }

/// <summary>
/// Oracle仓储接口
/// </summary>
public interface IOracleRepository<TEntity> : IRepository<int, TEntity, IUnitOfWork>
        where TEntity : SupplyChanEntity, new()
    {

    }

    public interface IRepository<TKey, TEntity, TUnitOfWork>
        where TEntity : Entity<TKey>, new()
        where TUnitOfWork : IUnitOfWork
    {
        #region 查询

        /// <summary>
        /// 是否存在满足指定条件的数据
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <returns></returns>
        bool IsExist(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 统计数据条数
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <returns></returns>
        int Count(Expression<Func<TEntity, bool>> whereExpression = null);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <returns></returns>
        Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 查询
        /// </summary>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync();

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="strWhere">查询字符串</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(string strWhere);

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="strWhere">查询字符串</param>
        /// <param name="strOrderByFileds">排序字段,如:Name Asc, Age Desc</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(string strWhere, string strOrderByFileds);

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="strOrderByFileds">排序字段,如:Name Asc, Age Desc</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds);

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="orderByExpression">排序表达式</param>
        /// <param name="isAsc">是否为升序</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true);

        /// <summary>
        /// 查询前 N 条数据
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="count">记录数</param>
        /// <param name="strOrderByFileds">排序字段,如:Name Asc, Age Desc</param>
        /// <returns></returns>
        Task<List<TEntity>> TopAsync(
            Expression<Func<TEntity, bool>> whereExpression,
            int count,
            string strOrderByFileds);

        /// <summary>
        /// 查询前 N 条数据
        /// </summary>
        /// <param name="strWhere">条件字符串</param>
        /// <param name="count">记录数</param>
        /// <param name="strOrderByFileds">排序字段,如:Name Asc, Age Desc</param>
        /// <returns></returns>
        Task<List<TEntity>> TopAsync(
            string strWhere,
            int count,
            string strOrderByFileds);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="strWhere">条件字符串</param>
        /// <param name="pageIndex">当前页数</param>
        /// <param name="pageSize">分页大小</param>
        /// <param name="strOrderByFileds">排序字段,如:Name Asc, Age Desc</param>
        /// <param name="totalCount">总记录数</param>
        /// <returns></returns>
        List<TEntity> Pages(string strWhere, int pageIndex, int pageSize, string strOrderByFileds, out int totalCount);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="pageIndex">当前页数</param>
        /// <param name="pageSize">分页大小</param>
        /// <param name="orderByExpression">排序表达式</param>
        /// <param name="isAsc">是否为升序</param>
        /// <param name="totalCount">总记录数</param>
        /// <returns></returns>
        List<TEntity> Pages(Expression<Func<TEntity, bool>> whereExpression,
            int pageIndex, int pageSize, Expression<Func<TEntity, object>> orderByExpression, bool isAsc,
            out int totalCount);

        /// <summary> 
        /// 多表查询
        /// </summary> 
        /// <typeparam name="T1">实体1</typeparam> 
        /// <typeparam name="T2">实体2</typeparam> 
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="joinExpression">关联表达式 (join1, join2) => new object[] { JoinType.Left, join1.UserNo == join2.UserNo }</param> 
        /// <param name="selectExpression">返回表达式 (s1, s2) => new { Id =s1.UserNo, Id1 = s2.UserNo }</param>
        /// <param name="whereLambda">查询表达式 (w1, w2) => w1.UserNo == "")</param> 
        /// <returns></returns>
        Task<List<TResult>> QueryMuchAsync<T1, T2, TResult>(
            Expression<Func<T1, T2, object[]>> joinExpression,
            Expression<Func<T1, T2, TResult>> selectExpression,
            Expression<Func<T1, T2, bool>> whereLambda = null) where T1 : class, new();

        /// <summary> 
        ///多表查询
        /// </summary>
        Task<List<TResult>> QueryMuchAsync<T1, T2, T3, TResult>(
            Expression<Func<T1, T2, T3, object[]>> joinExpression,
            Expression<Func<T1, T2, T3, TResult>> selectExpression,
            Expression<Func<T1, T2, T3, bool>> whereLambda = null) where T1 : class, new();

        /// <summary> 
        ///多表查询
        /// </summary>
        Task<List<TResult>> QueryMuchAsync<T1, T2, T3, T4, TResult>(
            Expression<Func<T1, T2, T3, T4, object[]>> joinExpression,
            Expression<Func<T1, T2, T3, T4, TResult>> selectExpression,
            Expression<Func<T1, T2, T3, T4, bool>> whereLambda = null) where T1 : class, new();

        Task<List<TResult>> QueryMuchAsync<T1, T2, T3, T4, T5, TResult>(
            Expression<Func<T1, T2, T3, T4, T5, object[]>> joinExpression,
            Expression<Func<T1, T2, T3, T4, T5, TResult>> selectExpression,
            Expression<Func<T1, T2, T3, T4, T5, bool>> whereLambda = null) where T1 : class, new();

        Task<List<TResult>> QueryMuchAsync<T1, T2, T3, T4, T5, T6, TResult>(
            Expression<Func<T1, T2, T3, T4, T5, T6, object[]>> joinExpression,
            Expression<Func<T1, T2, T3, T4, T5, T6, TResult>> selectExpression,
            Expression<Func<T1, T2, T3, T4, T5, T6, bool>> whereLambda = null) where T1 : class, new();

        #endregion

        #region 新增

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entities">实体(集合)</param>
        /// <returns></returns>
        Task<List<TEntity>> AddAsync(params TEntity[] entities);

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="insertColumns">指定要插入的列</param>
        /// <returns></returns>
        Task<TEntity> AddAsync(TEntity entity, Expression<Func<TEntity, object>> insertColumns);

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="insertColumns">指定要插入的列</param>
        /// <returns></returns>
        Task<List<TEntity>> AddAsync(TEntity[] entities, Expression<Func<TEntity, object>> insertColumns);

        #endregion

        #region 更新

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="updateColumns">指定要更新的列</param>
        /// <param name="ignoreColumns">指定要忽略的列</param>
        /// <returns></returns>
        Task<bool> UpdateAsync(TEntity entity,
            Expression<Func<TEntity, object>> updateColumns = null,
            Expression<Func<TEntity, object>> ignoreColumns = null);

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="updateColumns">指定要更新的列</param>
        /// <param name="ignoreColumns">指定要忽略的列</param>
        /// <returns></returns>
        Task<bool> UpdateAsync(TEntity[] entities,
            Expression<Func<TEntity, object>> updateColumns = null,
            Expression<Func<TEntity, object>> ignoreColumns = null);

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="anonymous">要更新的值(匿名对象)</param>
        /// <returns></returns>
        Task<int> UpdateAsync(Expression<Func<TEntity, bool>> whereExpression, dynamic anonymous);

        #endregion

        #region 删除

        /// <summary>
        /// 删除(Support IPhantomEntity)
        /// </summary>
        /// <param name="entities">实体(集合)</param>
        /// <returns></returns>
        Task<int> DeleteAsync(params TEntity[] entities);

        /// <summary>
        /// 删除(Support IPhantomEntity)
        /// </summary>
        /// <param name="ids">主键(集合)</param>
        /// <returns></returns>
        Task<int> DeleteAsync(params TKey[] ids);

        / <summary>
        / 删除(Support IPhantomEntity)
        / </summary>
        / <param name="whereExpression">条件表达式</param>
        / <returns></returns>
        //Task<int> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression);

        / <summary>
        / 删除(Support IPhantomEntity)
        / </summary>
        / <param name="strWhere">条件字符串</param>
        / <returns></returns>
        //Task<int> DeleteAsync(string strWhere);

        #endregion

        #region 更新或新增

        /// <summary>
        /// 更新或插入
        /// http://www.codeisbug.com/Doc/8/1172
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="upsertColumns">指定要更新或插入的列</param>
        /// <param name="ignoreColumns">指定要忽略的列</param>
        /// <returns></returns>
        TEntity UpsertAsync(TEntity entity,
            Expression<Func<TEntity, object>> upsertColumns = null,
            Expression<Func<TEntity, object>> ignoreColumns = null);

        /// <summary>
        /// 更新或插入
        /// http://www.codeisbug.com/Doc/8/1172
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="upsertColumns">指定要更新或插入的列</param>
        /// <param name="ignoreColumns">指定要忽略的列</param>
        /// <returns></returns>
        Task<List<TEntity>> UpsertAsync(List<TEntity> entities,
            Expression<Func<TEntity, object>> upsertColumns = null,
            Expression<Func<TEntity, object>> ignoreColumns = null);

        /// <summary>
        /// 更新或插入
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="insertColumns">指定要插入的列</param>
        /// <param name="ignoreInsertColumns">指定要忽略的插入列</param>
        /// <param name="updateColumns">指定要更新的列</param>
        /// <param name="ignoreUpdateColumns">指定要忽略的更新列</param>
        /// <returns></returns>
        TEntity UpsertAsync(TEntity entity,
            Expression<Func<TEntity, object>> insertColumns = null,
            Expression<Func<TEntity, object>> ignoreInsertColumns = null,
            Expression<Func<TEntity, object>> updateColumns = null,
            Expression<Func<TEntity, object>> ignoreUpdateColumns = null);

        /// <summary>
        /// 更新或插入
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="insertColumns">指定要插入的列</param>
        /// <param name="ignoreInsertColumns">指定要忽略的插入列</param>
        /// <param name="updateColumns">指定要更新的列</param>
        /// <param name="ignoreUpdateColumns">指定要忽略的更新列</param>
        /// <returns></returns>
        Task<List<TEntity>> UpsertAsync(List<TEntity> entities,
            Expression<Func<TEntity, object>> insertColumns = null,
            Expression<Func<TEntity, object>> ignoreInsertColumns = null,
            Expression<Func<TEntity, object>> updateColumns = null,
            Expression<Func<TEntity, object>> ignoreUpdateColumns = null);

        #endregion
    }

⭐ 通用实体

public abstract class Entity<TKey>
    {
        [SugarColumn(IsPrimaryKey = true)]
        public virtual TKey Id { get; set; }
    }

    public abstract class KdbndpEntity : Entity<Guid>, IPhantomEntity
    {
        public KdbndpEntity()
        {
            Id = GuidGenerator.Current.Create();
        }

        /// <summary>
        /// 创建时间
        /// </summary>
        [SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
        public virtual DateTime CreateTime { get; set; } = DateTime.Now;

        /// <summary>
        /// 更新时间
        /// </summary>
        [SugarColumn(ColumnName = "update_time", IsNullable = true, IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
        public virtual DateTime? UpdateTime { get; set; }

        [SugarColumn(ColumnName = SqlSugarConst.PhantomColumnName)]
        public bool IsDeleted { get; set; }
        public virtual string GetMainKey()
        {
            return this.Id.ToString();
        }
    }

⭐ 用户表实体

/// <summary>
    /// 用户表
    /// </summary>
    [SugarTable("sys_user")]
    public class User : KdbndpEntity
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public string Username { get; set; }
        /// <summary>
        /// 昵称
        /// </summary>
        public string Nickname { get; set; }
        /// <summary>
        /// 手机
        /// </summary>
        public string Phone { get; set; }
        /// <summary>
        /// 邮箱
        /// </summary>
        public string Email { get; set; }
        /// <summary>
        /// 密码
        /// </summary>
        public string Password { get; set; }

    }

♉ 各个仓储实现

⭐ 用户表仓储接口(人大金仓)

	/// <summary>
    /// 用户表仓储接口
    /// </summary>
    public interface IUserRepository : IKdbndpRepository<User>
    {
    }

⭐ 用户表仓储(人大金仓)

public class UserRepository : Repository<User>, IUserRepository
    {
        public UserRepository(KdbndpOfWork unitOfWork) : base(unitOfWork)
        {

        }
    }

⭐ 用户表仓储接口(达梦)

	/// <summary>
    /// 用户表仓储接口
    /// </summary>
    public interface IUserRepository : IDMRepository<User>
    {
    }

⭐ 用户表仓储(达梦)

public class UserRepository : Repository<User>, IUserRepository
    {
        public UserRepository(DMOfWork unitOfWork) : base(unitOfWork)
        {

        }
    }

⭐ 用户表仓储接口(翰高)

	/// <summary>
    /// 用户表仓储接口
    /// </summary>
    public interface IUserRepository : IHGRepository<User>
    {
    }

⭐ 用户表仓储(翰高)

public class UserRepository : Repository<User>, IUserRepository
    {
        public UserRepository(HGOfWork unitOfWork) : base(unitOfWork)
        {

        }
    }

⭐ 多表查询

public List<UserModel> Query(UserQuery query)
        {
            return Db.Queryable<User, UserRole>((p, userRole) => p.RoleId == userRole.Id)
                     .WhereIF(!IsNullOrEmpty(query.Username), p => p.Username.Contains(query.Username, StringComparison.OrdinalIgnoreCase))
                     .WhereIF(!IsNullOrEmpty(query.Nickname), p => p.Nickname == query.Nickname)
                     .WhereIF(!IsNullOrEmpty(query.RoleName), (p, userRole) => userRole.Id.Contains(query.Id, StringComparison.OrdinalIgnoreCase))
                     .Select((p, unitType) =>
                     
                         new UserModel()
                         {
                             Username = p.Username,
                             Nickname = p.Nickname,
                             CreateTime = p.CreateTime,
                             Phone = p.Phone,
                             Password = p.Password,
                             Id = p.Id,
                             RoleId = userRole.Id.ToString(),
                             UpdateTime = p.UpdateTime,
                             Email=p.Email
                         }
                     ).ToList();
                     
        }

📙 结语

​ 本文主要介绍了SqlSugar使用工作单元模式操作多个数据库的实战,包括多类型MySQL、人大金仓、达梦等数据,或者同一种数据库的多个库。


文章中出现的任何错误请大家批评指出,一定及时修改。

希望写在这里的小伙伴能给个三连支持

有关猿创征文|【国产数据库】一文学会应用SqlSugar工作单元模式操作多数据库的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  3. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  8. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  9. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  10. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

随机推荐