zoukankan      html  css  js  c++  java
  • 第十九节:EFCore连接MySQL各种场景深度剖析测试

    一. 说明

    1. 环境准备

    (1).测试载体:.Net Core3.1 控制台

    (2).数据库:MySQL 5.7 (事先改为大小写敏感 lower_case_table_names=0)

    (3).EFCore相关程序集:(这里统一用3.1.10版本)

     Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.Design、Microsoft.EntityFrameworkCore.Tools

    (4).MySQL相关程序集:

     A. MySQL官方出品:MySql.Data.EntityFrameworkCore (版本:8.0.22)

     B. 社区出品:Pomelo.EntityFrameworkCore.MySql (版本:3.2.4)

    2. 配置日志

     为了便于调优,配置日志,把linq转换成SQL输出来.

     安装程序集:【Microsoft.Extensions.Logging.Console】

      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
                optionsBuilder.UseLoggerFactory(LoggerFactory.Create(build =>
                {
                    build.AddConsole();  // 用于控制台程序的输出
                }));
                optionsBuilder.UseMySql("server=localhost;database=CoreFrameDB;user id=root;password=123456", x => x.ServerVersion("5.7.28-mysql"));
      }

    3. DB准备

     这里为了配合框架,使用的CoreFrameDB数据库,详见数据库说明书,并且新增一张T_Test,用于演示MySQL各种数据类型的映射.

     

    二. 映射剖析

    1. 映射指令测试

     A.首次映射:详见指令文档

     B.修改后映射:-Force,会把上下午和全部实体的变化都修改一下

     C.局部映射: -tables,根据情况选择使用,他会把上下文中已经多余的关联实体关系删掉,仅保留 -tables后面表, 多余的实体并不修改, 谨慎使用。

    指令分享:

    ----------------------------------------------------------------------------------------------------------下面是MySQL版的指令----------------------------------------------------------------
    
    
    一. Pomelo.EntityFrameworkCore.MySql
    --全局新增
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" Pomelo.EntityFrameworkCore.MySql -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -DataAnnotations
    
    --全局修改
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" Pomelo.EntityFrameworkCore.MySql -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -DataAnnotations  -Force
    
    -- 部分修改,没有上面bug
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" Pomelo.EntityFrameworkCore.MySql  -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -Tables T_Test -DataAnnotations  -Force
    
    
    
    一. MySql.Data.EntityFrameworkCore
    --全局新增
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" MySql.Data.EntityFrameworkCore -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -DataAnnotations
    --全局修改
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" MySql.Data.EntityFrameworkCore -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -DataAnnotations  -Force
    -- 部分修改,注意:这里有个bug,只要加上 -Tables,映射过来的实体就全是小写
    Scaffold-DbContext "Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456;" MySql.Data.EntityFrameworkCore  -OutputDir Entity -Context CoreFrameDBContext -UseDatabaseNames -Tables T_Test -DataAnnotations  -Force
    View Code

    映射上下文和部分实体分享:

      public partial class CoreFrameDBContext : DbContext
        {
            public CoreFrameDBContext()
            {
            }
    
            public CoreFrameDBContext(DbContextOptions<CoreFrameDBContext> options)
                : base(options)
            {
            }
    
            public virtual DbSet<T_SysErrorLog> T_SysErrorLog { get; set; }
            public virtual DbSet<T_SysLoginLog> T_SysLoginLog { get; set; }
            public virtual DbSet<T_SysOperLog> T_SysOperLog { get; set; }
            public virtual DbSet<T_SysPermisson> T_SysPermisson { get; set; }
            public virtual DbSet<T_SysRole> T_SysRole { get; set; }
            public virtual DbSet<T_SysRolePer> T_SysRolePer { get; set; }
            public virtual DbSet<T_SysUser> T_SysUser { get; set; }
            public virtual DbSet<T_SysUserRole> T_SysUserRole { get; set; }
            public virtual DbSet<T_Test> T_Test { get; set; }
    
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
    
                optionsBuilder.UseLoggerFactory(LoggerFactory.Create(build =>
                {
                    build.AddConsole();  // 用于控制台程序的输出
                }));
    
                optionsBuilder.UseMySql("server=localhost;database=CoreFrameDB;user id=root;password=123456", x => x.ServerVersion("5.7.28-mysql"));
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<T_SysErrorLog>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.logLevel)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.logMessage)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userAccount)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userId)
                        .HasCharSet("ascii")
                        .HasCollation("ascii_general_ci");
                });
    
                modelBuilder.Entity<T_SysLoginLog>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.loginCity)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.loginIp)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userAccount)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysOperLog>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.operMessage)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userAccount)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysPermisson>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.actionName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.areaName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.controllerName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.iconClassName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.menuName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.parentId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.remarkContent)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysRole>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.roleName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.roleRemark)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysRolePer>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.perId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.roleId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysUser>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userAccount)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userPhone)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userPicture)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userPwd)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userRealName)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userRemark)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_SysUserRole>(entity =>
                {
                    entity.Property(e => e.id)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.roleId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.userId)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                modelBuilder.Entity<T_Test>(entity =>
                {
                    entity.HasIndex(e => e.name1)
                        .HasName("ids_name1");
    
                    entity.HasIndex(e => new { e.age1, e.age2 })
                        .HasName("ids_age");
    
                    entity.Property(e => e.name1)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.name2)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.name3)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.name4)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.name5)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
    
                    entity.Property(e => e.name6)
                        .HasCharSet("utf8")
                        .HasCollation("utf8_general_ci");
                });
    
                OnModelCreatingPartial(modelBuilder);
            }
    
            partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
        }
     public partial class T_SysErrorLog
        {
            [Key]
            [Column(TypeName = "varchar(32)")]
            public string id { get; set; }
            [Required]
            [Column(TypeName = "varchar(32)")]
            public string userId { get; set; }
            [Column(TypeName = "varchar(50)")]
            public string userAccount { get; set; }
            [Column(TypeName = "varchar(50)")]
            public string logLevel { get; set; }
            [Column(TypeName = "varchar(10000)")]
            public string logMessage { get; set; }
            [Column(TypeName = "datetime")]
            public DateTime? addTime { get; set; }
            [Column(TypeName = "int(5)")]
            public int? delFlag { get; set; }
        }
      public partial class T_Test
        {
            [Key]
            [Column(TypeName = "int(10)")]
            public int id { get; set; }
            [Column(TypeName = "tinyint(10)")]
            public sbyte? age1 { get; set; }
            [Column(TypeName = "smallint(255)")]
            public short? age2 { get; set; }
            [Column(TypeName = "mediumint(255)")]
            public int? age3 { get; set; }
            [Column(TypeName = "int(10)")]
            public int? age4 { get; set; }
            [Column(TypeName = "bigint(255)")]
            public long? age5 { get; set; }
            [Column(TypeName = "float(18,2)")]
            public float? money1 { get; set; }
            [Column(TypeName = "double(20,3)")]
            public double? money2 { get; set; }
            [Column(TypeName = "decimal(20,2)")]
            public decimal? money3 { get; set; }
            [Column(TypeName = "year(4)")]
            public short? addTime1 { get; set; }
            [Column(TypeName = "date")]
            public DateTime? addTime2 { get; set; }
            [Column(TypeName = "time")]
            public TimeSpan? addTime3 { get; set; }
            [Column(TypeName = "datetime")]
            public DateTime? addTime4 { get; set; }
            [Column(TypeName = "timestamp")]
            public DateTime? addTime5 { get; set; }
            [Column(TypeName = "char(5)")]
            public string name1 { get; set; }
            [Column(TypeName = "varchar(6)")]
            public string name2 { get; set; }
            [Column(TypeName = "tinytext")]
            public string name3 { get; set; }
            [Column(TypeName = "text")]
            public string name4 { get; set; }
            [Column(TypeName = "mediumtext")]
            public string name5 { get; set; }
            [Column(TypeName = "longtext")]
            public string name6 { get; set; }
            [Column(TypeName = "bit(4)")]
            public ulong? isSex1 { get; set; }
    
            [Timestamp]
            [Column(TypeName = "timestamp")]
            public DateTime? rowVersion { get; set; }
        }
    View Code

    注:mysql中的 datetime、timestamp类型对应C#中的都是DateTime类型,但是EFCore使用【MySql.Data.EntityFrameworkCore】无法反向生成,使用【Pomelo.EntityFrameworkCore.MySql】可以反向生成。所以本章节都是基于基于【Pomelo.EntityFrameworkCore.MySql】来进行。

    2.数据类型对应测试

    3.补充EFCore数据注解属性

     参考:https://docs.microsoft.com/zh-cn/ef/core/modeling/

          https://www.cnblogs.com/yaopengfei/p/7813120.html

     部分特性如下: [NotMapped]、 [Required]、 [Column("blog_id")]、 [Key]、 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]、 [ConcurrencyCheck]、 [Timestamp]。

    PS:关于数据注解后续再EFCore系列中单独写一个章节进行测试。

    三. 实战测试

    前言:

     以下测试都基于【Pomelo.EntityFrameworkCore.MySql】来进行。

    1. 基础CRUD(+封装)

      经测试,均可正常使用。

    封装方法:

     /// <summary>
        /// 泛型方法,直接注入EF上下文
        /// </summary>
        public class BaseService { 
            public DbContext db;
    
            /// <summary>
            /// 在使用的时候,自动注入db上下文
            /// </summary>
            /// <param name="db"></param>
            public BaseService(DbContext db)
            {
                this.db = db;
    
                //关闭全局追踪的代码
                //db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            }
    
            /****************************************下面进行方法的封装(同步)***********************************************/
            //1. 直接提交数据库
    
            #region 01-数据源
            public IQueryable<T> Entities<T>() where T : class
            {
                return db.Set<T>();
            }
    
            public IQueryable<T> EntitiesNoTrack<T>() where T : class
            {
                return db.Set<T>().AsNoTracking();
            }
    
            #endregion
    
            #region 02-新增
            public int Add<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Added;
                return db.SaveChanges();
    
            }
            #endregion
    
            #region 03-删除
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="model">需要删除的实体</param>
            /// <returns></returns>
            public int Del<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Deleted;
                return db.SaveChanges();
            }
            #endregion
    
            #region 04-根据条件删除(支持批量删除)
            /// <summary>
            /// 根据条件删除(支持批量删除)
            /// </summary>
            /// <param name="delWhere">传入Lambda表达式(生成表达式目录树)</param>
            /// <returns></returns>
            public int DelBy<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                List<T> listDels = db.Set<T>().Where(delWhere).ToList();
                listDels.ForEach(model =>
                {
                    db.Entry(model).State = EntityState.Deleted;
                });
                return db.SaveChanges();
            }
            #endregion
    
            #region 05-单实体修改
            /// <summary>
            /// 修改
            /// </summary>
            /// <param name="model">修改后的实体</param>
            /// <returns></returns>
            public int Modify<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Modified;
                return db.SaveChanges();
            }
            #endregion
    
            #region 06-批量修改(非lambda)
            /// <summary>
            /// 批量修改(非lambda)
            /// </summary>
            /// <param name="model">要修改实体中 修改后的属性 </param>
            /// <param name="whereLambda">查询实体的条件</param>
            /// <param name="proNames">lambda的形式表示要修改的实体属性名</param>
            /// <returns></returns>
            public int ModifyBy<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] proNames) where T : class
            {
                List<T> listModifes = db.Set<T>().Where(whereLambda).ToList();
                Type t = typeof(T);
                List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
                Dictionary<string, PropertyInfo> dicPros = new Dictionary<string, PropertyInfo>();
                proInfos.ForEach(p =>
                {
                    if (proNames.Contains(p.Name))
                    {
                        dicPros.Add(p.Name, p);
                    }
                });
                foreach (string proName in proNames)
                {
                    if (dicPros.ContainsKey(proName))
                    {
                        PropertyInfo proInfo = dicPros[proName];
                        object newValue = proInfo.GetValue(model, null);
                        foreach (T m in listModifes)
                        {
                            proInfo.SetValue(m, newValue, null);
                        }
                    }
                }
                return db.SaveChanges();
            }
            #endregion
    
            #region 07-根据条件查询
            /// <summary>
            /// 根据条件查询
            /// </summary>
            /// <param name="whereLambda">查询条件(lambda表达式的形式生成表达式目录树)</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetListBy<T>(Expression<Func<T, bool>> whereLambda, bool isTrack = true) where T : class
            {
                if (isTrack)
                {
                    return db.Set<T>().Where(whereLambda).ToList();
                }
                else
                {
                    return db.Set<T>().Where(whereLambda).AsNoTracking().ToList();
                }
               
            }
            #endregion
    
            #region 08-根据条件排序和查询
            /// <summary>
            /// 根据条件排序和查询
            /// </summary>
            /// <typeparam name="Tkey">排序字段类型</typeparam>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="orderLambda">排序条件</param>
            /// <param name="isAsc">升序or降序</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetListBy<T, Tkey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true, bool isTrack = true) where T : class
            {
                IQueryable<T> data = null;         
                if (isTrack)
                {
                    data = db.Set<T>().Where(whereLambda);
                }
                else
                {
                    data = db.Set<T>().Where(whereLambda).AsNoTracking();
                }
                if (isAsc)
                {
                    data = data.OrderBy(orderLambda);
                }
                else
                {
                    data = data.OrderByDescending(orderLambda);
                }
                return data.ToList();
            }
            #endregion
    
            #region 09-分页查询(根据Lambda排序)
            /// <summary>
            /// 根据条件排序和查询
            /// </summary>
            /// <typeparam name="Tkey">排序字段类型</typeparam>
            /// <param name="pageIndex">页码</param>
            /// <param name="pageSize">页容量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="orderLambda">排序条件</param>
            /// <param name="isAsc">升序or降序</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetPageList<T, Tkey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true, bool isTrack = true) where T : class
            {
    
                IQueryable<T> data = null;
                if (isTrack)
                {
                    data = db.Set<T>().Where(whereLambda);
                }
                else
                {
                    data = db.Set<T>().Where(whereLambda).AsNoTracking();
                }
                if (isAsc)
                {
                    data = data.OrderBy(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                else
                {
                    data = data.OrderByDescending(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                return data.ToList();
            }
            #endregion
    
            #region 10-分页查询(根据名称排序)
            /// <summary>
            /// 分页查询输出总行数(根据名称排序)
            /// </summary>
            /// <param name="pageIndex">页码</param>
            /// <param name="rowCount">输出的总数量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="sortName">排序名称</param>
            /// <param name="sortDirection">asc 或 desc</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetPageListByName<T>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, string sortName, string sortDirection, bool isTrack = true) where T : class
            {
                List<T> list = null;
                if (isTrack)
                {
                    list = db.Set<T>().Where(whereLambda).DataSorting(sortName, sortDirection)
                     .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                }
                else
                {
                    list = db.Set<T>().Where(whereLambda).AsNoTracking().DataSorting(sortName, sortDirection)
                     .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                }
                return list;
            }
            #endregion
    
            #region 11-分页查询输出总行数(根据Lambda排序)
            /// <summary>
            /// 根据条件排序和查询
            /// </summary>
            /// <typeparam name="Tkey">排序字段类型</typeparam>
            /// <param name="pageIndex">页码</param>
            /// <param name="pageSize">页容量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="orderLambda">排序条件</param>
            /// <param name="isAsc">升序or降序</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetPageList<T, Tkey>(int pageIndex, int pageSize, out int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true, bool isTrack = true) where T : class
            {
                int count = db.Set<T>().Where(whereLambda).Count();
                IQueryable<T> data = null;
                if (isTrack)
                {
                    data = db.Set<T>().Where(whereLambda);
                }
                else
                {
                    data = db.Set<T>().Where(whereLambda).AsNoTracking();
                }
                if (isAsc)
                {
                    data=data.OrderBy(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                else
                {
                    data = data.OrderByDescending(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                rowCount = count;
                return data.ToList();
            }
            #endregion
    
            #region 12-分页查询输出总行数(根据名称排序)
            /// <summary>
            /// 分页查询输出总行数(根据名称排序)
            /// </summary>
            /// <param name="pageIndex">页码</param>
            /// <param name="pageSize">页容量</param>
            /// <param name="rowCount">输出的总数量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="sortName">排序名称</param>
            /// <param name="sortDirection">asc 或 desc</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public List<T> GetPageListByName<T>(int pageIndex, int pageSize, out int rowCount, Expression<Func<T, bool>> whereLambda, string sortName, string sortDirection, bool isTrack = true) where T : class
            {
                int count = 0;
                count = db.Set<T>().Where(whereLambda).Count();
                List<T> list = null;
                if (isTrack)
                {
                    list= db.Set<T>().Where(whereLambda).DataSorting(sortName, sortDirection)
                     .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                }
                else
                {
                    list = db.Set<T>().Where(whereLambda).AsNoTracking().DataSorting(sortName, sortDirection)
                       .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
    
                }
                rowCount = count;
                return list;
            }
            #endregion
    
    
            //2. SaveChange剥离出来,处理事务
    
            #region 01-批量处理SaveChange()
            /// <summary>
            /// 事务批量处理
            /// </summary>
            /// <returns></returns>
            public int SaveChange()
            {
                return db.SaveChanges();
            }
            #endregion
    
            #region 02-新增
            /// <summary>
            /// 新增
            /// </summary>
            /// <param name="model">需要新增的实体</param>
            public void AddNo<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Added;
            }
            #endregion
    
            #region 03-删除
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="model">需要删除的实体</param>
            public void DelNo<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Deleted;
            }
            #endregion
    
            #region 04-根据条件删除
            /// <summary>
            /// 条件删除
            /// </summary>
            /// <param name="delWhere">需要删除的条件</param>
            public void DelByNo<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                List<T> listDels = db.Set<T>().Where(delWhere).ToList();
                listDels.ForEach(model =>
                {
                    db.Entry(model).State = EntityState.Deleted;
                });
            }
            #endregion
    
            #region 05-修改
            /// <summary>
            /// 修改
            /// </summary>
            /// <param name="model">修改后的实体</param>
            public void ModifyNo<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Modified;
            }
            #endregion
    
    
            //3. EF调用sql语句
    
            #region 01-执行增加,删除,修改操作(或调用相关存储过程)
            /// <summary>
            /// 执行增加,删除,修改操作(或调用存储过程)
            /// </summary>
            /// <param name="sql"></param>
            /// <param name="pars"></param>
            /// <returns></returns>
            public int ExecuteSql(string sql, params SqlParameter[] pars)
            {
                return db.Database.ExecuteSqlRaw(sql, pars);
            }
    
            #endregion
    
            #region 02-执行查询操作(调用查询类的存储过程)
            /// <summary>
            /// 执行查询操作
            /// 注:查询必须返回实体的所有属性字段;结果集中列名必须与属性映射的项目匹配;查询中不能包含关联数据
            /// 除Select以外其他的SQL语句无法执行
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="sql"></param>
            /// <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <param name="pars"></param>
            /// <returns></returns>
            public List<T> ExecuteQuery<T>(string sql, bool isTrack = true, params SqlParameter[] pars) where T : class
            {
                if (isTrack)
                {
                    //表示跟踪状态(默认是跟踪的)
                    return db.Set<T>().FromSqlRaw(sql, pars).ToList();
                }
                else
                {
                    //表示不跟踪状态
                    return db.Set<T>().FromSqlRaw(sql, pars).AsNoTracking().ToList();
                }
            }
            #endregion
    
            #region 03-执行查询操作(与Linq相结合)
            /// <summary>
            /// 执行查询操作
            /// 注:查询必须返回实体的所有属性字段;结果集中列名必须与属性映射的项目匹配;查询中不能包含关联数据
            /// 除Select以外其他的SQL语句无法执行
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="sql"></param>
            ///  <param name="whereLambda">查询条件</param>
            /// <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <param name="pars"></param>
            /// <returns></returns>
            public List<T> ExecuteQueryWhere<T>(string sql, Expression<Func<T, bool>> whereLambda, bool isTrack = true, params SqlParameter[] pars) where T : class
            {
                if (isTrack)
                {
                    //表示跟踪状态(默认是跟踪的)
                    return db.Set<T>().FromSqlRaw(sql, pars).Where(whereLambda).ToList();
                }
                else
                {
                    //表示不跟踪状态
                    return db.Set<T>().FromSqlRaw(sql, pars).Where(whereLambda).AsNoTracking().ToList();
                }
            }
            #endregion
    
    
    
            /****************************************下面进行方法的封装(异步)***********************************************/
    
            #region 01-新增
            public async Task<int> AddAsync<T>(T model) where T : class
            {
                await db.AddAsync(model);
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 02-删除
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="model">需要删除的实体</param>
            /// <returns></returns>
            public async Task<int> DelAsync<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Deleted;
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 03-根据条件删除(支持批量删除)
            /// <summary>
            /// 根据条件删除(支持批量删除)
            /// </summary>
            /// <param name="delWhere">传入Lambda表达式(生成表达式目录树)</param>
            /// <returns></returns>
            public async Task<int> DelByAsync<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                List<T> listDels = await db.Set<T>().Where(delWhere).ToListAsync();
                listDels.ForEach(model =>
                {
                    db.Entry(model).State = EntityState.Deleted;
                });
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 04-单实体修改
            /// <summary>
            /// 修改
            /// </summary>
            /// <param name="model">修改后的实体</param>
            /// <returns></returns>
            public async Task<int> ModifyAsync<T>(T model) where T : class
            {
                db.Entry(model).State = EntityState.Modified;
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 05-批量修改(非lambda)
            /// <summary>
            /// 批量修改(非lambda)
            /// </summary>
            /// <param name="model">要修改实体中 修改后的属性 </param>
            /// <param name="whereLambda">查询实体的条件</param>
            /// <param name="proNames">lambda的形式表示要修改的实体属性名</param>
            /// <returns></returns>
            public async Task<int> ModifyByAsync<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] proNames) where T : class
            {
                List<T> listModifes = await db.Set<T>().Where(whereLambda).ToListAsync();
                Type t = typeof(T);
                List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
                Dictionary<string, PropertyInfo> dicPros = new Dictionary<string, PropertyInfo>();
                proInfos.ForEach(p =>
                {
                    if (proNames.Contains(p.Name))
                    {
                        dicPros.Add(p.Name, p);
                    }
                });
                foreach (string proName in proNames)
                {
                    if (dicPros.ContainsKey(proName))
                    {
                        PropertyInfo proInfo = dicPros[proName];
                        object newValue = proInfo.GetValue(model, null);
                        foreach (T m in listModifes)
                        {
                            proInfo.SetValue(m, newValue, null);
                        }
                    }
                }
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 06-根据条件查询
            /// <summary>
            /// 根据条件查询
            /// </summary>
            /// <param name="whereLambda">查询条件(lambda表达式的形式生成表达式目录树)</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public async Task<List<T>> GetListByAsync<T>(Expression<Func<T, bool>> whereLambda, bool isTrack = true) where T : class
            {
                if (isTrack)
                {
                    return await db.Set<T>().Where(whereLambda).ToListAsync();
                }
                else
                {
                    return await db.Set<T>().Where(whereLambda).AsNoTracking().ToListAsync();
                }
    
            }
            #endregion
    
            #region 07-根据条件排序和查询
            /// <summary>
            /// 根据条件排序和查询
            /// </summary>
            /// <typeparam name="Tkey">排序字段类型</typeparam>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="orderLambda">排序条件</param>
            /// <param name="isAsc">升序or降序</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public async Task<List<T>> GetListByAsync<T, Tkey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true, bool isTrack = true) where T : class
            {
                IQueryable<T> data = null;
                if (isTrack)
                {
                    data = db.Set<T>().Where(whereLambda);
                }
                else
                {
                    data = db.Set<T>().Where(whereLambda).AsNoTracking();
                }
                if (isAsc)
                {
                    data = data.OrderBy(orderLambda);
                }
                else
                {
                    data = data.OrderByDescending(orderLambda);
                }
                return await data.ToListAsync();
            }
            #endregion
    
            #region 08-分页查询(根据Lambda排序)
            /// <summary>
            /// 根据条件排序和查询
            /// </summary>
            /// <typeparam name="Tkey">排序字段类型</typeparam>
            /// <param name="pageIndex">页码</param>
            /// <param name="pageSize">页容量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="orderLambda">排序条件</param>
            /// <param name="isAsc">升序or降序</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public async Task<List<T>>  GetPageListAsync<T, Tkey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true, bool isTrack = true) where T : class
            {
    
                IQueryable<T> data = null;
                if (isTrack)
                {
                    data = db.Set<T>().Where(whereLambda);
                }
                else
                {
                    data = db.Set<T>().Where(whereLambda).AsNoTracking();
                }
                if (isAsc)
                {
                    data = data.OrderBy(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                else
                {
                    data = data.OrderByDescending(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                }
                return await data.ToListAsync();
            }
            #endregion
    
            #region 09-分页查询(根据名称排序)
            /// <summary>
            /// 分页查询输出总行数(根据名称排序)
            /// </summary>
            /// <param name="pageIndex">页码</param>
            /// <param name="rowCount">输出的总数量</param>
            /// <param name="whereLambda">查询条件</param>
            /// <param name="sortName">排序名称</param>
            /// <param name="sortDirection">asc 或 desc</param>
            ///  <param name="isTrack">是否跟踪状态,默认是跟踪的</param>
            /// <returns></returns>
            public async Task<List<T>> GetPageListByNameAsync<T>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, string sortName, string sortDirection, bool isTrack = true) where T : class
            {
                List<T> list = null;
                if (isTrack)
                {
                    list = await db.Set<T>().Where(whereLambda).DataSorting(sortName, sortDirection)
                     .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
                }
                else
                {
                    list = await db.Set<T>().Where(whereLambda).AsNoTracking().DataSorting(sortName, sortDirection)
                     .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
                }
                return list;
            }
            #endregion
    
     
    
            //2. SaveChange剥离出来,处理事务
    
            #region 01-批量处理SaveChange()
            /// <summary>
            /// 事务批量处理
            /// </summary>
            /// <returns></returns>
            public async Task<int> SaveChangeAsync()
            {
                return await db.SaveChangesAsync();
            }
            #endregion
    
            #region 02-新增
            /// <summary>
            /// 新增
            /// </summary>
            /// <param name="model">需要新增的实体</param>
            public async Task<EntityEntry<T>> AddNoAsync<T>(T model) where T : class
            {
               return await db.AddAsync(model);
            }
            #endregion
            
            #region 03-根据条件删除
            /// <summary>
            /// 条件删除
            /// </summary>
            /// <param name="delWhere">需要删除的条件</param>
            public async Task DelByNoAsync<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                List<T> listDels =await db.Set<T>().Where(delWhere).ToListAsync();
                listDels.ForEach(model =>
                {
                    db.Entry(model).State = EntityState.Deleted;
                });
            }
            #endregion
    
    
            //3. EF调用sql语句
    
            #region 01-执行增加,删除,修改操作(或调用存储过程)
            /// <summary>
            /// 执行增加,删除,修改操作(或调用存储过程)
            /// </summary>
            /// <param name="sql"></param>
            /// <param name="pars"></param>
            /// <returns></returns>
            public async Task<int> ExecuteSqlAsync(string sql, params SqlParameter[] pars)
            {
                return await db.Database.ExecuteSqlRawAsync(sql, pars);
            }
            #endregion
    
    
            /****************************************下面是基于【EFCore.BulkExtensions】大数据的处理 (同步)***********************************************/
    
            #region 01-增加
            /// <summary>
            /// 增加
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public void BulkInsert<T>(List<T> list) where T : class
            {
                db.BulkInsert<T>(list);
            }
            #endregion
    
            #region 02-修改
            /// <summary>
            /// 修改
            /// PS:传入的实体如果不赋值,则更新为null,即传入的实体每个字段都要有值
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public void BulkUpdate<T>(List<T> list) where T : class
            {
                db.BulkUpdate<T>(list);
            }
            #endregion
    
            #region 03-删除
            /// <summary>
            /// 删除
            /// PS:传入的list中的实体仅需要主键有值,它是根据主键删除的
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public void BulkDelete<T>(List<T> list) where T : class
            {
                db.BulkDelete<T>(list);
            }
            #endregion
    
            #region 04-条件删除
            /// <summary>
            /// 条件删除
            /// </summary>
            /// <param name="delWhere">需要删除的条件</param>
            public int BatchDelete<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                return db.Set<T>().Where(delWhere).BatchDelete();
            }
            #endregion
    
            #region 05-条件更新1
            /// <summary>
            /// 条件更新
            /// PS:要更新哪几个字段,就给传入的实体中的哪几个字段赋值
            /// </summary>
            /// <param name="delWhere">需要更新的条件</param>
            /// <param name="model">更新为的实体</param>
            public int BatchUpdate<T>(Expression<Func<T, bool>> delWhere, T model) where T : class, new()
            {
                return db.Set<T>().Where(delWhere).BatchUpdate(model);
            }
            #endregion
    
            #region 06-条件更新2
            /// <summary>
            /// 条件更新
            /// PS:要更新哪几个字段,就给传入的实体中的哪几个字段赋值
            /// </summary>
            /// <param name="delWhere">需要更新的条件</param>
            /// <param name="model">更新为的实体</param>
            public int BatchUpdate2<T>(Expression<Func<T, bool>> delWhere, Expression<Func<T, T>> modelWhere) where T : class, new()
            {
                return db.Set<T>().Where(delWhere).BatchUpdate(modelWhere);
            }
            #endregion
    
    
            /****************************************下面是基于【EFCore.BulkExtensions】大数据的处理 (异步)***********************************************/
    
            #region 01-增加
            /// <summary>
            /// 增加
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public async void BulkInsertAsync<T>(List<T> list) where T : class
            {
                await db.BulkInsertAsync<T>(list);
            }
            #endregion
    
            #region 02-修改
            /// <summary>
            /// 修改
            /// PS:传入的实体如果不赋值,则更新为null,即传入的实体每个字段都要有值
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public async void BulkUpdateAsync<T>(List<T> list) where T : class
            {
                await db.BulkUpdateAsync<T>(list);
            }
            #endregion
    
            #region 03-删除
            /// <summary>
            /// 删除
            /// PS:传入的list中的实体仅需要主键有值,它是根据主键删除的
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            public async void BulkDeleteAsync<T>(List<T> list) where T : class
            {
                await db.BulkDeleteAsync<T>(list);
            }
            #endregion
    
            #region 04-条件删除
            /// <summary>
            /// 条件删除
            /// </summary>
            /// <param name="delWhere">需要删除的条件</param>
            public async Task<int> BatchDeleteAsync<T>(Expression<Func<T, bool>> delWhere) where T : class
            {
                return await db.Set<T>().Where(delWhere).BatchDeleteAsync();
            }
            #endregion
    
            #region 05-条件更新1
            /// <summary>
            /// 条件更新
            /// PS:要更新哪几个字段,就给传入的实体中的哪几个字段赋值
            /// </summary>
            /// <param name="delWhere">需要更新的条件</param>
            /// <param name="model">更新为的实体</param>
            public async  Task<int> BatchUpdateAsync<T>(Expression<Func<T, bool>> delWhere, T model) where T : class, new()
            {
                return await db.Set<T>().Where(delWhere).BatchUpdateAsync(model);
            }
            #endregion
    
            #region 06-条件更新2
            /// <summary>
            /// 条件更新
            /// PS:要更新哪几个字段,就给传入的实体中的哪几个字段赋值
            /// </summary>
            /// <param name="delWhere">需要更新的条件</param>
            /// <param name="model">更新为的实体</param>
            public async Task<int> BatchUpdate2Async<T>(Expression<Func<T, bool>> delWhere, Expression<Func<T, T>> modelWhere) where T : class, new()
            {
                return await db.Set<T>().Where(delWhere).BatchUpdateAsync(modelWhere);
            }
            #endregion
    
        }
     /// <summary>
        /// 排序的扩展
        /// </summary>
        public static class SortExtension
        {
    
            #region 01-根据string名称排序扩展(单字段)
            /// <summary>
            /// 根据string名称排序扩展(单字段)
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="source">排序数据源</param>
            /// <param name="sortName">排序名称</param>
            /// <param name="sortDirection">排序方式 asc或desc</param>
            /// <returns></returns>
            public static IQueryable<T> DataSorting<T>(this IQueryable<T> source, string sortName, string sortDirection)
            {
                string sortingDir = string.Empty;
                if (sortDirection.ToUpper().Trim() == "ASC")
                {
                    sortingDir = "OrderBy";
                }
                else if (sortDirection.ToUpper().Trim() == "DESC")
                {
                    sortingDir = "OrderByDescending";
                }
                ParameterExpression param = Expression.Parameter(typeof(T), sortName);
                PropertyInfo pi = typeof(T).GetProperty(sortName);
                Type[] types = new Type[2];
                types[0] = typeof(T);
                types[1] = pi.PropertyType;
                Expression expr = Expression.Call(typeof(Queryable), sortingDir, types, source.Expression, Expression.Lambda(Expression.Property(param, sortName), param));
                IQueryable<T> query = source.AsQueryable().Provider.CreateQuery<T>(expr);
                return query;
            }
            #endregion
    
            #region 02-根据多个string名称排序扩展(多字段)
            /// <summary>
            ///  根据多个string名称排序扩展(多字段)
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="data">数据源</param>
            /// <param name="orderParams">排序类</param>
            /// <returns></returns>
            public static IQueryable<T> DataManySorting<T>(this IQueryable<T> data, params FiledOrderParam[] orderParams) where T : class
            {
                var parameter = Expression.Parameter(typeof(T), "p");
                if (orderParams != null && orderParams.Length > 0)
                {
                    for (int i = 0; i < orderParams.Length; i++)
                    {
                        var property = typeof(T).GetProperty(orderParams[i].PropertyName);
                        if (property != null)
                        {
                            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                            var orderByExpr = Expression.Lambda(propertyAccess, parameter);
                            string methodName = i > 0 ?
                                orderParams[i].IsDesc ? "ThenByDescending" : "ThenBy"
                                : orderParams[i].IsDesc ? "OrderByDescending" : "OrderBy";
                            var resultExp = Expression.Call(
                                typeof(Queryable), methodName,
                                new Type[] { typeof(T), property.PropertyType },
                                data.Expression, Expression.Quote(orderByExpr)
                                );
                            data = data.Provider.CreateQuery<T>(resultExp);
                        }
                    }
                }
                return data;
            }
    
            #endregion
        }
    
    
        /// <summary>
        /// 排序类
        /// </summary>
        public class FiledOrderParam
        {
            //是否降序
            public bool IsDesc { get; set; }
            //排序名称
            public string PropertyName { get; set; }
        }
    View Code

    测试代码: 

                   #region 01-增加
                    {
                        //T_Test tTest = new T_Test()
                        //{
                        //    age1 = 1,
                        //    age2 = 2,
                        //    age3 = 3,
                        //    age4 = 4,
                        //    age5 = 5,
                        //    money1 = (float)10.12,
                        //    money2 = 20.34,
                        //    money3 = (decimal)12.13,
                        //    addTime1 = 2020,
                        //    addTime2 = DateTime.Now,
                        //    addTime3 = TimeSpan.FromMinutes(10),
                        //    addTime4 = DateTime.Now,
                        //    addTime5 = DateTime.Now,
                        //    name1 = "ypf1",
                        //    name2 = "ypf2",
                        //    name3 = "ypf3",
                        //    name4 = "ypf4",
                        //    name5 = "ypf5",
                        //    name6 = "ypf6",
                        //    isSex1 = 1
                        //};
                        //int count1 = baseService.Add(tTest);
    
                        //T_SysErrorLog sErrorLog = new T_SysErrorLog();
                        //sErrorLog.id = Guid.NewGuid().ToString("N");
                        //sErrorLog.userId = "001";
                        //sErrorLog.userAccount = "12345";
                        //sErrorLog.logLevel = "Error";
                        //sErrorLog.logMessage = "出错了";
                        //sErrorLog.addTime = DateTime.Now;
                        //sErrorLog.delFlag = 0;
                        //int count2 = baseService.Add(sErrorLog);
                    }
                    #endregion
    
                    #region 02-修改
                    //{
                    //    var data = baseService.Entities<T_SysErrorLog>().Where(u => u.id == "1").FirstOrDefault();
                    //    data.userAccount = "123456";
                    //    baseService.SaveChange();
                    //    Console.WriteLine("修改成功");
                    //}
                    #endregion
    
                    #region 03-删除
                    //{
                    //    baseService.DelBy<T_SysErrorLog>(u => u.id != "1");
                    //    Console.WriteLine("删除成功");
                    //}
                    #endregion
    
                    #region 04-根据条件查询和排序
                    //{
                    //    var list = baseService.GetListBy<T_SysErrorLog, DateTime?>(u => u.id != "xxx", p => p.addTime, false);
                    //    foreach (var item in list)
                    //    {
                    //        Console.WriteLine($"id={item.id},userId={item.userId},userAccount={item.userAccount},addTime={item.addTime}");
                    //    }
    
                    //} 
                    #endregion
    
                    #region 05-根据字段名称升/降序分页查询
                    //{
                    //    int pageIndex = 1;
                    //    int pageSize = 2;
                    //    //1.分开写法
                    //    var list1 = baseService.Entities<T_SysErrorLog>().Where(u => u.id != "fk").DataSorting("addTime", "desc").Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                    //    //2. 封装调用
                    //    int count = 0;
                    //    var list2 = baseService.GetPageListByName<T_SysErrorLog>(pageIndex, pageSize, out count, u => u.id != "fk", "addTime", "desc");
    
                    //    //3.多字段排序
                    //    FiledOrderParam[] param = {
                    //        new FiledOrderParam(){IsDesc=false,PropertyName="addTime"},
                    //        new FiledOrderParam(){IsDesc=true,PropertyName="id"}
                    //    };
                    //    var list3 = baseService.Entities<T_SysErrorLog>().Where(u => u.id != "fk").DataManySorting(param).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
                    //}
                    #endregion
    View Code

    2. 各种Linq测试

     详细测试了各种linq对应MySQL的翻译,代码如下:

                    #region 01-First/Last/Single/ElementAt
                    //{
                    //    //说明:First/FirstOrDefault 翻译limit 1, Last/LastOrDefault不能翻译  Single/SingleOrDefault翻译成limit 2, ElementAt/ElementAtOrDefault不能翻译
    
                    //    db.T_SysErrorLog.First();
                    //    db.T_SysErrorLog.FirstOrDefault();
    
                    //    db.T_SysErrorLog.Last();
                    //    db.T_SysErrorLog.LastOrDefault();
    
                    //    var d1 = db.T_SysErrorLog.Single();
                    //    var d2 = db.T_SysErrorLog.SingleOrDefault();
    
                    //    var d3 = db.T_SysErrorLog.ElementAt(1);
                    //    var d4 = db.T_SysErrorLog.ElementAtOrDefault(1);
    
                    //}
                    #endregion
    
                    #region 02-Select相关
                    //{
                    //    //正常翻译select
                    //    var d1 = (from a in db.T_SysErrorLog
                    //              select a.logLevel).ToList();
                    //    //翻译出来别名和计算
                    //    var d2 = (from a in db.T_SysErrorLog
                    //              select new
                    //              {
                    //                  a.logLevel,
                    //                  a.addTime,
                    //                  myMsg = a.logMessage,
                    //                  myflag = a.delFlag / 2
                    //              }).ToList();
    
                    //    //这种嵌套无法翻译,报错
                    //    var d3 = (from a in db.T_SysErrorLog
                    //              select new
                    //              {
                    //                  a.logLevel,
                    //                  a.addTime,
                    //                  myMsg = from b in db.T_SysUser
                    //                          select b.userAccount,
                    //                  myflag = a.delFlag / 2
                    //              }).ToList();
    
                    //}
                    #endregion
    
                    #region 03-基本函数
                    {
                        //1.以下基础函数都可以翻译成对应的mysql中的函数
                        //db.T_SysErrorLog.Count();
                        //db.T_SysErrorLog.Select(o => o.delFlag).Sum();
                        //db.T_SysErrorLog.Sum(o => o.delFlag);
                        //db.T_SysErrorLog.Select(o => o.delFlag).Max();
                        //db.T_SysErrorLog.Select(o => o.delFlag).Min();
                        //db.T_SysErrorLog.Select(o => o.delFlag).Average();
    
    
    
                    }
                    #endregion
    
                    #region 04-关联查询
                    //{
    
                    //    //隐式内连接 翻译成 cross join (在mysql中,join、cross join、inner join含义相同)
                    //    var data1 = (from a in db.T_SysUser
                    //                 from b in db.T_SysLoginLog
                    //                 where a.id == b.userId
                    //                 select new
                    //                 {
                    //                     a.userAccount,
                    //                     a.userPhone,
                    //                     b.loginCity,
                    //                     b.loginIp,
                    //                     b.loginTime
                    //                 }).ToList();
    
                    //    //显式内连接 翻译成inner join 
                    //    var data2 = (from a in db.T_SysUser
                    //                 join b in db.T_SysLoginLog
                    //                 on a.id equals b.userId
                    //                 select new
                    //                 {
                    //                     a.userAccount,
                    //                     a.userPhone,
                    //                     b.loginCity,
                    //                     b.loginIp,
                    //                     b.loginTime
                    //                 }).ToList();
    
                    //    //外链接翻译成 left join (linq中通过颠倒数据位置实现left 或 right join)
                    //    var data3 = (from a in db.T_SysUser
                    //                 join b in db.T_SysLoginLog
                    //                 on a.id equals b.userId into fk
                    //                 from c in fk.DefaultIfEmpty()
                    //                 select new
                    //                 {
                    //                     a.userAccount,
                    //                     a.userPhone,
                    //                     c.loginCity,
                    //                     c.loginIp,
                    //                     c.loginTime
                    //                 }).ToList();
    
                    //    //统计右表的数量,报错,翻译不出来!!
                    //    var data4 = (from a in db.T_SysUser
                    //                 join b in db.T_SysLoginLog
                    //                 on a.id equals b.userId into fk
                    //                 select new
                    //                 {
                    //                     a.userAccount,
                    //                     a.userPhone,
                    //                     myCount = fk.Count()
                    //                 }).ToList();
    
    
                    //}
                    #endregion
    
                    #region 05-排序
                    //{
                    //    //升序和降序 正常翻译 mysql的排序
                    //    var d1 = db.T_SysErrorLog.OrderBy(u => u.addTime).ThenByDescending(u => u.delFlag).ToList();
                    //    var d2 = (from a in db.T_SysErrorLog
                    //              orderby a.addTime, a.delFlag descending
                    //              select a).ToList();
                    //}
                    #endregion
    
                    #region 06-分组
                    //{
    
                    //    //前提:必须加.AsEnumerable(),否则报错
                    //    //以下经测试均可以使用,但是翻译的sql语句不显示group
                    //    var d1 = (from a in db.T_SysErrorLog.AsEnumerable()
                    //              group a by a.delFlag into g
                    //              select g).ToList();
    
                    //    var d2 = (from a in db.T_SysErrorLog.AsEnumerable()
                    //              group a by a.delFlag into g
                    //              select new
                    //              {
                    //                  myKey = g.Key,
                    //                  g
                    //              }).ToList();
    
                    //    var d3 = (from a in db.T_SysErrorLog.AsEnumerable()
                    //              group a by new { myFlag = a.delFlag != 2 } into g
                    //              select new
                    //              {
                    //                  myKey = g.Key,
                    //                  g
                    //              }).ToList();
                    //}
                    #endregion
    
                    #region 07-分页
                    //{
                    //    //翻译成mysql的 limit+offset用法,注意不是单独的limit用法
                    //    var d1 = db.T_SysErrorLog.Skip(2).Take(10).ToList();
    
                    //    //下面两句都报错,无法翻译
                    //    var d2 = db.T_SysErrorLog.SkipWhile(u => u.delFlag ==0).ToList();
                    //    var d3 = db.T_SysErrorLog.TakeWhile(u => u.delFlag == 0).ToList();
                    //}
                    #endregion
    
                    #region 08-Contains/EF.Functions.Like/Concat/Union/Intersect/Except
                    //{
                    //    //1. 这里成Contains翻译到mysql中的in
                    //    string[] myList = { "222", "333", "444" };
                    //    string mystr = "222,333,444";
                    //    var d1 = db.T_SysErrorLog.Where(u => myList.Contains(u.logLevel)).ToList();
                    //    // 这里的contians翻译成 LIKE '%222%'     (sqlserver翻译成charindex)
                    //    var d2 = db.T_SysErrorLog.Where(u => u.logLevel.Contains("222")).ToList();
                    //    //这里的contians翻译成 LOCATE
                    //    //补充:locate(subStr,string) :函数返回subStr在string中出现的位置
                    //    var d3 = db.T_SysErrorLog.Where(u => mystr.Contains(u.logLevel)).ToList();
    
                    //    //2. 翻译成 LIKE '%222%
                    //    var d4 = db.T_SysErrorLog.Where(u => EF.Functions.Like(u.logLevel, "%222%")).ToList();
    
                    //    //3. 翻译成Union All 不去重
                    //    var d5 = ((from a in db.T_SysUser select a.id)
                    //           .Concat
                    //           (from a in db.T_SysRole select a.id)).ToList();
                    //    //翻译成Union 去重
                    //    var d6 = ((from a in db.T_SysUser select a.id)
                    //        .Union
                    //        (from a in db.T_SysRole select a.id)).ToList();
                    //    //无法翻译报错
                    //    var d7 = ((from a in db.T_SysUser select a.id)
                    //        .Intersect
                    //        (from a in db.T_SysRole select a.id)).ToList();
    
                    //    //无法翻译报错
                    //    var d8= ((from a in db.T_SysUser select a.id)
                    //        .Except
                    //        (from a in db.T_SysRole select a.id)).ToList();
    
    
                    //}
                    #endregion
    
                    #region 09-DateTime/String部分方法
                    //{
                    //    //翻译成 EXTRACT方法
                    //    var d1 = (from a in db.T_SysErrorLog
                    //             where a.addTime.Value.Year == 2019
                    //             select a).ToList();
                    //    //翻译成 Like
                    //    var d2 = (from a in db.T_SysErrorLog
                    //              where a.logLevel.StartsWith("333")
                    //              select a).ToList();
    
                    //    //翻译成 SUBSTRING
                    //    var d3 = (from a in db.T_SysErrorLog
                    //             select a.logLevel.Substring(0,5)).ToList();
                    //}
                    #endregion
    View Code

    3. 调用SQL语句

      经测试,可以正常使用。需要注意的是参数化查询要用 MySqlParameter。

    代码分享:

     #region 01-查询类(很鸡肋,只能单表全部查询,不能指定字段)
                    //{
                    //    //1.基本的原生SQL查询
                    //    var userList1 = db.Set<T_SysErrorLog>().FromSqlRaw("select * from T_SysErrorLog where id!='123'").ToList();
    
                    //    //2.利用$内插语法进行传递
                    //    var myId = "1";
                    //    var userList2 = db.Set<T_SysErrorLog>().FromSqlRaw($"select * from T_SysErrorLog where id= {myId}").ToList();
    
                    //    //3.原生SQL与linq语法相结合
                    //    var userList3 = db.Set<T_SysErrorLog>().FromSqlRaw($"select * from T_SysErrorLog")
                    //        .Where(u => u.id == "2")
                    //        .ToList();
                    //    var userList4 = db.Set<T_SysErrorLog>().FromSqlRaw($"select * from T_SysErrorLog")
                    //        .Where(u => u.id != "1111")
                    //        .OrderBy(u => u.addTime)
                    //        .ToList();
    
                    //    //4.利用SqlParameter进行参数化查询 MySql.Data.MySqlClient.MySqlParameter
                    //    MySqlParameter[] paras ={
                    //                             new MySqlParameter("@id","2fc343069e0a4a559b62b08d5999dbcd"),
                    //                             new MySqlParameter("@userAccount","ypf"),
                    //                        };
                    //    var userList5 = db.Set<T_SysErrorLog>().FromSqlRaw("select * from T_SysErrorLog where id=@id and userAccount=@userAccount", paras).ToList();
    
                    //} 
                    #endregion
    
                    #region 02-执行类(增删改)
                    //{
                    //    //1.增加
                    //    int result0 = db.Database.ExecuteSqlRaw("insert into T_SysErrorLog(id,userId,userAccount) values('44','11111','test1')");
                    //    int result1 = db.Database.ExecuteSqlRaw("insert into T_SysErrorLog(id,userId,userAccount) values('55','11111','test1')");
    
                    //    //2. 修改
                    //    MySqlParameter[] paras ={
                    //                                     new MySqlParameter("@id","1"),
                    //                                     new MySqlParameter("@userAccount","未知"),
                    //                                };
                    //    int result2 = db.Database.ExecuteSqlRaw("update T_SysErrorLog set userAccount=@userAccount where id=@id", paras);
    
                    //    //3. 删除
                    //    var myId = "44";
                    //    int result3 = db.Database.ExecuteSqlRaw($"delete from T_SysErrorLog where id={myId}");
    
                    //    //4. 其它指令
                    //    int result4 = db.Database.ExecuteSqlRaw("truncate table T_SysLoginLog");
                    //}
                    #endregion
    View Code

    4. 调用存储过程

      待补充,后续结合存储过程章节一起补充

    5. 事务

    (1).SaveChanges:经测试SaveChanges事务一体是好用的,但是下面关闭默认事务无效!!.

      db.Database.AutoTransactionsEnabled = false;可以关闭其默认事务。

    (2). DbContextTransaction:适用场景多次savechanges+SQL语句调用、多种数据库链接技术(EFCore和ADO.Net)

     A.场景多次savechanges+SQL语句调用:经测试,可以正常使用。

     B. 场景多种数据库链接技术(EFCore和ADO.Net):存在一个事务类型转换bug,暂时未没有解决.

    (3). 环境事务(TransactionScope)

     A.多个SaveChange+SQL场景:经测试,没问题。

     B.多种数据库链接技术(EFCore和ADO.Net)场景:存在一个事务类型转换bug,暂时未没有解决。

     C.多个EF上下链接同一个数据库:经测试,没问题。

    代码分享: 

                  #region 01-SaveChange事务
                    //{
                    //    try
                    //    {
    
                    //        for (int i = 0; i < 5; i++)
                    //        {
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                    //        }
                    //        //模拟失败
                    //        baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N")+"1", addTime = DateTime.Now });  //模拟失败
                    //        int count = baseService.SaveChange();
                    //    }
                    //    catch (Exception ex)
                    //    {
                    //        Console.WriteLine(ex.Message);
                    //    }
    
                    //}
                    #endregion
    
                    #region 02-DbContextTransaction(多个SaveChange)
                    //{
                    //    using (var transaction = db.Database.BeginTransaction())
                    //    {
                    //        //using包裹,catch中可以不用写rollback,自动回滚
                    //        try
                    //        {
                    //            //1. 业务1
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                    //            baseService.SaveChange();
    
                    //            //2. 业务2
                    //            db.Database.ExecuteSqlRaw($"insert into T_SysErrorLog(id,userId,userAccount) values('{Guid.NewGuid().ToString("N")}','11111','test1')");
    
                    //            //3.模拟失败
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                    //            baseService.SaveChange();
    
                    //            //统一提交
                    //            transaction.Commit();
                    //        }
                    //        catch (Exception ex)
                    //        {
                    //            Console.WriteLine(ex.Message);                     
                    //        }
                    //    }
    
                    //}
                    #endregion
    
                    #region 02-DbContextTransaction(多种数据库技术)--有bug
                    //{
                    //    var conStr = @"Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456";
                    //    using (var connection = new MySql.Data.MySqlClient.MySqlConnection(conStr))
                    //    {
                    //        connection.Open();
                    //        using (var transaction = db.Database.BeginTransaction())
                    //        {
                    //            try
                    //            {
                    //                //1. ADO.Net
                    //                var command = connection.CreateCommand();
                    //                command.Transaction = (MySqlTransaction)transaction;
                    //                command.CommandText = $"insert into T_SysErrorLog(id,userId,userAccount) values('{Guid.NewGuid().ToString("N")}','11111111111','test1')";
                    //                command.ExecuteNonQuery();
    
                    //                //2. EF Core
                    //                baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = "000000000000", addTime = DateTime.Now });
                    //                baseService.SaveChange();
    
    
                    //                //3.模拟失败
                    //                baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                    //                baseService.SaveChange();
    
    
                    //                //综合提交
                    //                transaction.Commit();
    
                    //            }
                    //            catch (Exception ex)
                    //            {
                    //                Console.WriteLine(ex.Message);
                    //            }
                    //        }
    
                    //    }
    
                    //}
                    #endregion
    
                    #region 03-TransactionScope(多个SaveChange+SQL)
                    //{
                    //    using (var transaction = new TransactionScope())
                    //    {
                    //        //using包裹,catch中可以不用写rollback,自动回滚
                    //        try
                    //        {
                    //            //1. 业务1
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                    //            baseService.SaveChange();
    
                    //            //2. 业务2
                    //            db.Database.ExecuteSqlRaw($"insert into T_SysErrorLog(id,userId,userAccount) values('{Guid.NewGuid().ToString("N")}','11111','test1')");
    
                    //            //3.模拟失败
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                    //            baseService.SaveChange();
    
                    //            //统一提交
                    //            transaction.Complete();
                    //        }
                    //        catch (Exception ex)
                    //        {
                    //            Console.WriteLine(ex.Message);
                    //        }
                    //    }
    
                    //}
                    #endregion
    
                    #region 03-TransactionScope(多种数据库技术)--有bug
                    //{
                    //    var conStr = @"Server=localhost;Database=CoreFrameDB;User ID=root;Password=123456";
                    //    using (var connection = new MySql.Data.MySqlClient.MySqlConnection(conStr))
                    //    {
                    //        connection.Open();
                    //        using (var transaction = new TransactionScope())
                    //        {
                    //            try
                    //            {
                    //                //1. ADO.Net
                    //                var command = connection.CreateCommand();
                    //                command.Transaction = (MySqlTransaction)transaction;
                    //                command.CommandText = $"insert into T_SysErrorLog(id,userId,userAccount) values('{Guid.NewGuid().ToString("N")}','11111111111','test1')";
                    //                command.ExecuteNonQuery();
    
                    //                //2. EF Core
                    //                baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = "000000000000", addTime = DateTime.Now });
                    //                baseService.SaveChange();
    
    
                    //                //3.模拟失败
                    //                baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                    //                baseService.SaveChange();
    
    
                    //                //综合提交
                    //                transaction.Complete();
    
                    //            }
                    //            catch (Exception ex)
                    //            {
                    //                Console.WriteLine(ex.Message);
                    //            }
                    //        }
    
                    //    }
    
                    //}
                    #endregion
    
                    #region 03-(同一个数据库不同上下)
                    //{
                    //    using (var scope = new TransactionScope())
                    //    {
                    //        try
                    //        {
                    //            //1.业务1
                    //            using (var context = new CoreFrameDBContext())
                    //            {
                    //                context.Add(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                    //                context.SaveChanges();
                    //            }
                    //            //2.业务2
                    //            using (var context = new CoreFrameDBContext2())
                    //            {
                    //                context.Add(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                    //                context.SaveChanges();
                    //            }
                    //            //3.模拟失败
                    //            baseService.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                    //            baseService.SaveChange();
    
                    //            //综合提交
                    //            scope.Complete();
    
                    //            Console.WriteLine("成功了");
                    //        }
                    //        catch (Exception ex)
                    //        {
                    //            Console.WriteLine(ex.Message);
                    //        }
                    //    }
    
                    //}
                    #endregion
    View Code

    6. 性能测试 

     

     结论:以上测试得出来一个结论,EFCore处理增删改在10000条数据以内速度还是可以接受的,并且EFCore调用SQL语句组装并不能提升性能,反而下降明显!!

     代码分享:

                 #region 01-增加(EFCore)
                    //{
                    //    for (int i = 0; i < 10; i++)
                    //    {
                    //        T_SysErrorLog sErrorLog = new T_SysErrorLog();
                    //        sErrorLog.id = Guid.NewGuid().ToString("N");
                    //        sErrorLog.userId = "001";
                    //        sErrorLog.userAccount = "12345";
                    //        sErrorLog.logLevel = "Error";
                    //        sErrorLog.logMessage = "出错了";
                    //        sErrorLog.addTime = DateTime.Now;
                    //        sErrorLog.delFlag = 0;
                    //        baseService.AddNo(sErrorLog);
                    //    }
                    //    int count = baseService.SaveChange();
                    //    Console.WriteLine("执行成功");
                    //}
                    #endregion
    
                    #region 01-增加(EFCore调用SQL)
                    //{
                    //    string sqlStr = "";
                    //    for (int i = 0; i < 1000; i++)
                    //    {
                    //        sqlStr = sqlStr + $"insert into T_SysErrorLog values('{Guid.NewGuid().ToString("N")}', '001', '12345','Error','出错了','{DateTime.Now}',0);";
                    //    }
                    //    int count = db.Database.ExecuteSqlRaw(sqlStr);
                    //    Console.WriteLine("执行成功");
                    //}
                    #endregion
    
                    #region 02-修改(EFCore)
                    //{
                    //    //先用上面的增加语句添加指定条目的数据
    
                    //    var list = baseService.GetListBy<T_SysErrorLog>(u => u.id != "000");
                    //    foreach (var item in list)
                    //    {
                    //        item.logLevel = "ERROR1110";
                    //        item.logMessage = "出错了2220";
                    //        item.addTime = DateTime.Now;
                    //    }
                    //    int count = baseService.SaveChange();
    
                    //}
                    #endregion
    
                    #region 02-修改(EFCore调用SQL)
                    //{
                    //    //先用上面的增加语句添加指定条目的数据
                    //    var list = baseService.GetListBy<T_SysErrorLog>(u => u.id != "000");
                    //    string sqlStr = "";
                    //    foreach (var item in list)
                    //    {
                    //        sqlStr = sqlStr + $"update T_SysErrorLog set logLevel='ERROR110',logMessage='出错了220',addTime='{DateTime.Now}' where id='{item.id}';";
                    //    }
                    //    int count = db.Database.ExecuteSqlRaw(sqlStr);
                    //    Console.WriteLine("执行成功");
                    //}
                    #endregion
    
                    #region 03-删除(EFCore)
                    //{
                    //    //先用上面的增加语句添加指定条目的数据
                    //    int count = baseService.DelBy<T_SysErrorLog>(u => u.id != "fk");
    
                    //}
                    #endregion
    
                    #region 03-删除(EFCore调用SQL)
                    //{
                    //    //先用上面的增加语句添加指定条目的数据
                    //    var list = baseService.Entities<T_SysErrorLog>().Where(u => u.id != "000").Select(u => u.id).ToList();
                    //    string sqlStr = "";
                    //    foreach (var item in list)
                    //    {
                    //        sqlStr = sqlStr + $"delete from T_SysErrorLog where id='{item}';";
                    //    }
                    //    int count = db.Database.ExecuteSqlRaw(sqlStr);
                    //    Console.WriteLine("执行成功");
                    //}
                    #endregion
    View Code

    7. 性能优化

    (1).SqlBulkCopy:基于 System.Data.SqlClient ,仅支持SQLServer, Pass掉。

    (2).EFCore.BulkExtensions:仅支持SQLServer 和 SQLite,Pass掉

    (3).Z.EntityFramework.Plus.EFCore:

    A.说明:免费, 支持MySQL,,且目前已经支持EFCore5.x版本了, 但功能有限, 仅支持:Batch Delete、Batch Update. (删除和修改)

     GitHub地址:https://github.com/zzzprojects/EntityFramework-Plus

     官网文档地址:http://entityframework-plus.net/batch-delete

    注意:更强大的BulkSaveChanges、 BulkInsert、 BulkUpdate、BulkDelete、BulkMerge 对应收费的程序集 Z.EntityFramework.Extensions (收费!!!)

    B.性能测试:

    C. 测试是否支持事务:

     经测试,支持Transaction事务的统一提交和回滚。

    最后总结:目前只找到大数据删除和修改的组件,增加的组件目前没有找到!!!

    代码分享:

       {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    Console.WriteLine("开始执行。。。。。。");
    
                    #region 01-删除
                    //{
                    //    int count1 = db.T_SysErrorLog.Where(u => u.id != "1").Delete();
                    //    //db.T_SysErrorLog.Where(u => u.id != "1").Delete(x => x.BatchSize = 1000);
                    //} 
                    #endregion
    
                    #region 02-修改
                    //{
                    //    int count1 = db.T_SysErrorLog.Where(u => u.id != "1").Update(x=>new T_SysErrorLog() { logLevel="Error33324",logMessage="出3错4342了",addTime=DateTime.Now});
    
                    //} 
                    #endregion
    
                    #region 03-测试事务
                    {
                        using (var transaction = db.Database.BeginTransaction())
                        {
                            BaseService baseService1 = new BaseService(db);
                            //using包裹,不需要手动写rollback
                            try
                            {
                                //1.普通增加
                                for (int i = 0; i < 5; i++)
                                {
                                    baseService.AddNo(new T_SysErrorLog() { id = i.ToString(), userId = Guid.NewGuid().ToString("N"), addTime = DateTime.Now });
                                }
                                baseService.SaveChange();
    
                                //2. 组件的删除
                                db.T_SysErrorLog.Where(u => u.id == "1").Delete();
    
                                //3. 组件的更新
                                db.T_SysErrorLog.Where(u => u.id != "0001").Update(x => new T_SysErrorLog() { logLevel = "Error33324", logMessage = "出3错4342了", addTime = DateTime.Now });
    
                                //4. 模拟失败
                                baseService1.AddNo(new T_SysErrorLog() { id = Guid.NewGuid().ToString("N"), userId = Guid.NewGuid().ToString("N") + "1", addTime = DateTime.Now });  //模拟失败
                                baseService1.SaveChange();
    
                                //5.最后提交
                                transaction.Commit();
    
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
    
                            }
                        }
    
                    }
                    #endregion
    
    
    
                    Console.WriteLine("执行完成");
                    watch.Stop();
                    Console.WriteLine($"时间为:{watch.ElapsedMilliseconds}ms");
                }
    View Code

    PS:上述代码事务的时候必须是同一个db

    8. 并发测试

    (1). 监测单个字段: [ConcurrencyCheck] 或 entity.Property(p => p.age).IsConcurrencyToken();

     配置T_Test表中的age4字段,进行测试, 有效可以使用。

    (2). 监测整条数据:[Timestamp]或entity.Property(e => e.rowVersion).IsRowVersion();

     配置T_Test表新增timestamp类型的rowVersion字段,实体中进行上述配置,进行测试, 发现无效不能使用!!!

    代码分享:

       #region 01-单字段监控
                    //{
                    //    CoreFrameDBContext db1 = new CoreFrameDBContext();
                    //    CoreFrameDBContext db2 = new CoreFrameDBContext();
                    //    try
                    //    {
                    //        var data1 = db1.T_Test.Where(u => u.id == 1).FirstOrDefault();
                    //        var data2 = db2.T_Test.Where(u => u.id ==1).FirstOrDefault();
    
                    //        data1.age4 = data1.age4 - 2;
                    //        int result1 = db1.SaveChanges();
    
                    //        data2.age4 = data2.age4 - 4;
                    //        int result2 = db2.SaveChanges();  //发现age的值和原先查出来的不一致,会抛异常进入cache
                    //    }
                    //    catch (DbUpdateConcurrencyException ex)
                    //    {
    
                    //        var entityEntry = ex.Entries.Single();
                    //        var original = entityEntry.OriginalValues.ToObject() as T_Test; //数据库原始值  10
                    //        var database = entityEntry.GetDatabaseValues().ToObject() as T_Test; //数据库现在值 8
                    //        var current = entityEntry.CurrentValues.ToObject() as T_Test; //当前内存值 6
                    //        entityEntry.Reload(); //放弃当前内存中的实体,重新到数据库中加载当前实体
    
                    //        current.age4 = database.age4 - 4;  //应该拿着当前数据库实际的值去处理,即8-4=4
                    //        entityEntry.CurrentValues.SetValues(current);
                    //        int result3 = db2.SaveChanges();
                    //    }
                    //}
                    #endregion
    
                    #region 02-全字段监控
                    //{
                    //    CoreFrameDBContext db1 = new CoreFrameDBContext();
                    //    CoreFrameDBContext db2 = new CoreFrameDBContext();
                    //    try
                    //    {
                    //        var data1 = db1.T_Test.Where(u => u.id == 1).FirstOrDefault();
                    //        var data2 = db2.T_Test.Where(u => u.id == 1).FirstOrDefault();
    
                    //        data1.age4 = data1.age4 - 2;
                    //        int result1 = db1.SaveChanges();
    
                    //        data2.age4 = data2.age4 - 4;
                    //        int result2 = db2.SaveChanges();  //发现age的值和原先查出来的不一致,会抛异常进入cache
                    //    }
                    //    catch (DbUpdateConcurrencyException ex)
                    //    {
    
                    //        var entityEntry = ex.Entries.Single();
                    //        var original = entityEntry.OriginalValues.ToObject() as T_Test; //数据库原始值  10
                    //        var database = entityEntry.GetDatabaseValues().ToObject() as T_Test; //数据库现在值 8
                    //        var current = entityEntry.CurrentValues.ToObject() as T_Test; //当前内存值 6
                    //        entityEntry.Reload(); //放弃当前内存中的实体,重新到数据库中加载当前实体
    
                    //        current.age4 = database.age4 - 4;  //应该拿着当前数据库实际的值去处理,即8-4=4
                    //        entityEntry.CurrentValues.SetValues(current);
                    //        int result3 = db2.SaveChanges();
                    //    }
                    //}
                    #endregion
    View Code

    9. 索引映射

     给T_Test表中的name1添加索引,age1和age2添加联合索引,通过指令映射,发现索引映射成功。

    entity.HasIndex(e => e.name1).HasName("ids_name1");
    
    entity.HasIndex(e => new { e.age1, e.age2}).HasName("ids_age");

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    Pythontutor:可视化代码在内存的执行过程
    katalon系列六:Katalon Studio Web UI关键字讲解
    chrome flash插件改为自动运行
    katalon系列五:使用Katalon Studio手动编写WEB自动化脚本
    JMeter随机上传附件
    JDK11安装后,环境变量的坑
    katalon系列四:使用Katalon Studio录制WEB自动化脚本
    katalon系列三:Project Setting-项目设置
    tomcat服务器上https的SSL证书安装配置
    eclipse安装freemarker插件
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/14004719.html
Copyright © 2011-2022 走看看