using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Repository
{
    public class Repository : IRepository
    {

        public DbContext GetCurrentDbContext()
        {
            var context = new TeamDataContext();
            return context;
        }

        public bool Add<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().Add(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> AddAsync<T>(T entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            await context.Set<T>().AddAsync(entity);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool AddRange<T>(IEnumerable<T> entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().AddRange(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> AddRangeAsync<T>(IEnumerable<T> entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            await context.Set<T>().AddRangeAsync(entity);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }
        public bool Delete<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().Attach(entity);
            context.Set<T>().Remove(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public bool DeleteAll<T>() where T : class
        {
            using var context = GetCurrentDbContext();
            var entities = context.Set<T>().ToArray();
            if (entities.Length == 0)
            {
                return false;
            }
            context.Set<T>().RemoveRange(entities);
            var count = context.SaveChanges();
            return true;
        }
        public async Task<bool> DeleteAllAsync<T>() where T : class
        {
            await using var context = GetCurrentDbContext();
            var entities = await context.Set<T>().ToArrayAsync();
            if (entities.Length == 0)
            {
                return false;
            }
            context.Set<T>().RemoveRange(entities);
            var count = context.SaveChanges();
            return true;
        }
        public bool Delete<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Set<T>().Where(whereLambda).FirstOrDefault();
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> DeleteAsync<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = await context.Set<T>().Where(whereLambda).FirstOrDefaultAsync();
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool DeleteById<T>(dynamic id) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Set<T>().Find(id);
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> DeleteByIdAsync<T>(dynamic id) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = await context.Set<T>().FindAsync(id);
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool Update<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Entry(entity);
            context.Set<T>().Attach(entity);
            entityModel.State = EntityState.Modified;
            var count = context.SaveChanges();
            return count > 0;
        }
        public async Task<bool> UpdateAsync<T>(T entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = context.Entry(entity);
            context.Set<T>().Attach(entity);
            entityModel.State = EntityState.Modified;
            var count = await context.SaveChangesAsync();
            return count > 0;

        }



        public bool Update<T>(List<T> entities) where T : class
        {
            using var context = GetCurrentDbContext();
            if (entities != null)
            {
                foreach (var item in entities)
                {
                    var entityModel = context.Entry(entities);
                    context.Set<T>().Attach(item);
                    entityModel.State = EntityState.Modified;
                }
            }
            var count = context.SaveChanges();
            return count > 0;
        }

        //查询要修改的数据
        public bool Update<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) where T : class
        {
            using var context = GetCurrentDbContext();
            var listModifying = context.Set<T>().Where(whereLambda).ToList();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            var ditProList = new Dictionary<string, PropertyInfo>();
            proInfos.ForEach(p =>
            {
                if (modifiedProNames.Contains(p.Name))
                {
                    ditProList.Add(p.Name, p);
                }
            });

            if (ditProList.Count <= 0)
            {
                throw new Exception("指定修改的字段名称有误或为空");
            }
            foreach (var item in ditProList)
            {
                var proInfo = item.Value;
                var newValue = proInfo.GetValue(model, null);
                //批量进行修改相互对应的属性
                foreach (var oModel in listModifying)
                {
                    proInfo.SetValue(oModel, newValue, null);//设置其中新的值
                }
            }
            return context.SaveChanges() > 0;

        }
        public T FindById<T>(dynamic id) where T : class
        {
            using var context = GetCurrentDbContext();
            return context.Set<T>().Find(id);
        }

        public async Task<T> FindByIdAsync<T>(dynamic id) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await context.Set<T>().FindAsync(id);
        }


        public T GetFirstDefault<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null
                ? context.Set<T>().Where(whereLambda).FirstOrDefault()
                : context.Set<T>().FirstOrDefault();
        }

        public async Task<T> GetFirstDefaultAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return whereLambda != null
                ? await context.Set<T>().Where(whereLambda).FirstOrDefaultAsync()
                : await context.Set<T>().FirstOrDefaultAsync();

        }
        public List<T> GetAll<T>(string orderProperty = null) where T : class
        {
            using var context = GetCurrentDbContext();
            if (orderProperty == null)
            {
                return context.Set<T>().ToList();
            }

            var properties = typeof(T).GetProperties().Select(c => c.Name);

            if (!properties.Contains(orderProperty))
            {
                throw new Exception("Not Find Property Exception");
            }

            return context.Set<T>().OrderBy(c => c.GetType().GetProperties().First(p => p.Name == orderProperty))
                .ToList();
        }

        public async Task<List<T>> GetAllAsync<T>(string orderProperty = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            if (orderProperty == null)
            {
                return await context.Set<T>().ToListAsync();
            }

            var properties = typeof(T).GetProperties().Select(c => c.Name);

            if (!properties.Contains(orderProperty))
            {
                throw new Exception("Not Find Property Exception");
            }

            return await context.Set<T>().OrderBy(c => c.GetType().GetProperties().First(p => p.Name == orderProperty))
                .ToListAsync();

        }
        public List<T> GetAllQuery<T>(string path, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).Include(path).ToList() : context.Set<T>().Include(path).ToList();
        }
        public List<T> GetAllQuery<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).ToList() : context.Set<T>().ToList();

        }

        public async Task<List<T>> GetAllQueryAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).ToListAsync()
                : context.Set<T>().ToListAsync());

        }

        public int GetCount<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null
                ? context.Set<T>().Where(whereLambda).Count()
                : context.Set<T>().Count();
        }
        public async Task<int> GetCountAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).CountAsync()
                : context.Set<T>().CountAsync());
        }

        public bool GetAny<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).Any() : context.Set<T>().Any();
        }

        public async Task<bool> GetAnyAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).AnyAsync()
                : context.Set<T>().AnyAsync());
        }

        public List<T> Pagination<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy,
            Expression<Func<T, bool>> whereLambda = null, bool isOrder = true) where T : class
        {
            using var context = GetCurrentDbContext();
            IQueryable<T> queryList =
                isOrder ? context.Set<T>().OrderBy(orderBy) : context.Set<T>().OrderByDescending(orderBy);

            if (whereLambda != null)
            {
                queryList = queryList.Where(whereLambda);
            }

            return queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        }

        public async Task<List<T>> PaginationAsync<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy,
            Expression<Func<T, bool>> whereLambda = null, bool isOrder = true) where T : class
        {
            await using var context = GetCurrentDbContext();
            IQueryable<T> queryList =
                isOrder ? context.Set<T>().OrderBy(orderBy) : context.Set<T>().OrderByDescending(orderBy);

            if (whereLambda != null)
            {
                queryList = queryList.Where(whereLambda);
            }

            return await queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();
        }

        public List<T> Pagination<T>(int pageIndex, int pageSize, string ordering, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            var ditProList = new Dictionary<string, PropertyInfo>();
            using var context = GetCurrentDbContext();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            proInfos.ForEach(p => { ditProList.Add(p.Name, p); });

            //分页的时候一定要注意 Order 一定在Skip 之前
            var queryList = context.Set<T>()
                .OrderBy(c => c.GetType().GetProperties().First(p => p.Name == ordering).Name);
            if (whereLambda != null)
            {
                queryList = (IOrderedQueryable<T>)queryList.Where(whereLambda);
            }

            return queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        }

        public async Task<List<T>> PaginationAsync<T>(int pageIndex, int pageSize, string ordering, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            var ditProList = new Dictionary<string, PropertyInfo>();
            proInfos.ForEach(p => { ditProList.Add(p.Name, p); });

            //分页的时候一定要注意 Order 一定在Skip 之前
            var queryList = context.Set<T>()
                .OrderBy(c => c.GetType().GetProperties().First(p => p.Name == ordering).Name);
            if (whereLambda != null)
            {
                queryList = (IOrderedQueryable<T>)queryList.Where(whereLambda);
            }

            return await queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();
        }

        public List<T> GetSelect<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            using var context = GetCurrentDbContext();
            return context.Set<T>().Where(whereLambda).ToList();
        }

        public List<T> QueryPro<T>(string sql, List<SqlParameter> parameters, CommandType cmdType = CommandType.Text) where T : class
        {
            using var context = GetCurrentDbContext();
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            var array = parameters.ToArray();
            var sqlParams = array.Select(item => item).Cast<object>().ToList();
            //进行执行存储过程
            if (cmdType != CommandType.StoredProcedure)
                return context.Set<T>().FromSqlRaw(sql, sqlParams).ToList();


            var paraNames = new StringBuilder();
            foreach (var item in parameters)
            {
                paraNames.Append($" @{item},");
            }

            sql = paraNames.Length > 0 ? $"exec {sql} {paraNames.ToString().Trim(',')}" : $"exec {sql} ";
            return context.Set<T>().FromSqlRaw(sql, sqlParams).ToList();
        }

        public void RollBackChanges<T>() where T : class
        {
            using var context = GetCurrentDbContext();
            var query = context.ChangeTracker.Entries().ToList();
            query.ForEach(p => p.State = EntityState.Unchanged);
        }

        public bool Update<T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, T>> updateLambda) where T : class
        {
            throw new NotImplementedException();
        }

        public Task<bool> UpdateAsync<T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, T>> updateLambda) where T : class
        {
            throw new NotImplementedException();
        }
    }


    public class CustomRepository : IRepository
    {

        public DbContext GetCurrentDbContext()
        {
            var context = new CustomerDataContext();
            return context;
        }

        public bool Add<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().Add(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> AddAsync<T>(T entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            await context.Set<T>().AddAsync(entity);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool AddRange<T>(IEnumerable<T> entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().AddRange(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> AddRangeAsync<T>(IEnumerable<T> entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            await context.Set<T>().AddRangeAsync(entity);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }
        public bool Delete<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            context.Set<T>().Attach(entity);
            context.Set<T>().Remove(entity);
            var count = context.SaveChanges();
            return count > 0;
        }

        public bool DeleteAll<T>() where T : class
        {
            using var context = GetCurrentDbContext();
            var entities = context.Set<T>().ToArray();
            if (entities.Length == 0)
            {
                return false;
            }
            context.Set<T>().RemoveRange(entities);
            var count = context.SaveChanges();
            return true;
        }
        public async Task<bool> DeleteAllAsync<T>() where T : class
        {
            await using var context = GetCurrentDbContext();
            var entities = await context.Set<T>().ToArrayAsync();
            if (entities.Length == 0)
            {
                return false;
            }
            context.Set<T>().RemoveRange(entities);
            var count = context.SaveChanges();
            return true;
        }
        public bool Delete<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Set<T>().Where(whereLambda).FirstOrDefault();
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> DeleteAsync<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = await context.Set<T>().Where(whereLambda).FirstOrDefaultAsync();
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool DeleteById<T>(dynamic id) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Set<T>().Find(id);
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = context.SaveChanges();
            return count > 0;
        }

        public async Task<bool> DeleteByIdAsync<T>(dynamic id) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = await context.Set<T>().FindAsync(id);
            if (entityModel == null) return false;
            context.Set<T>().Remove(entityModel);
            var count = await context.SaveChangesAsync();
            return count > 0;
        }

        public bool Update<T>(T entity) where T : class
        {
            using var context = GetCurrentDbContext();
            var entityModel = context.Entry(entity);
            context.Set<T>().Attach(entity);
            entityModel.State = EntityState.Modified;
            var count = context.SaveChanges();
            return count > 0;
        }
        public async Task<bool> UpdateAsync<T>(T entity) where T : class
        {
            await using var context = GetCurrentDbContext();
            var entityModel = context.Entry(entity);
            context.Set<T>().Attach(entity);
            entityModel.State = EntityState.Modified;
            var count = await context.SaveChangesAsync();
            return count > 0;

        }



        public bool Update<T>(List<T> entities) where T : class
        {
            using var context = GetCurrentDbContext();
            if (entities != null)
            {
                foreach (var item in entities)
                {
                    var entityModel = context.Entry(entities);
                    context.Set<T>().Attach(item);
                    entityModel.State = EntityState.Modified;
                }
            }
            var count = context.SaveChanges();
            return count > 0;
        }

        //查询要修改的数据
        public bool Update<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) where T : class
        {
            using var context = GetCurrentDbContext();
            var listModifying = context.Set<T>().Where(whereLambda).ToList();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            var ditProList = new Dictionary<string, PropertyInfo>();
            proInfos.ForEach(p =>
            {
                if (modifiedProNames.Contains(p.Name))
                {
                    ditProList.Add(p.Name, p);
                }
            });

            if (ditProList.Count <= 0)
            {
                throw new Exception("指定修改的字段名称有误或为空");
            }
            foreach (var item in ditProList)
            {
                var proInfo = item.Value;
                var newValue = proInfo.GetValue(model, null);
                //批量进行修改相互对应的属性
                foreach (var oModel in listModifying)
                {
                    proInfo.SetValue(oModel, newValue, null);//设置其中新的值
                }
            }
            return context.SaveChanges() > 0;

        }
        public T FindById<T>(dynamic id) where T : class
        {
            using var context = GetCurrentDbContext();
            return context.Set<T>().Find(id);
        }

        public async Task<T> FindByIdAsync<T>(dynamic id) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await context.Set<T>().FindAsync(id);
        }


        public T GetFirstDefault<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null
                ? context.Set<T>().Where(whereLambda).FirstOrDefault()
                : context.Set<T>().FirstOrDefault();
        }

        public async Task<T> GetFirstDefaultAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return whereLambda != null
                ? await context.Set<T>().Where(whereLambda).FirstOrDefaultAsync()
                : await context.Set<T>().FirstOrDefaultAsync();

        }
        public List<T> GetAll<T>(string orderProperty = null) where T : class
        {
            using var context = GetCurrentDbContext();
            if (orderProperty == null)
            {
                return context.Set<T>().ToList();
            }

            var properties = typeof(T).GetProperties().Select(c => c.Name);

            if (!properties.Contains(orderProperty))
            {
                throw new Exception("Not Find Property Exception");
            }

            return context.Set<T>().OrderBy(c => c.GetType().GetProperties().First(p => p.Name == orderProperty))
                .ToList();
        }

        public async Task<List<T>> GetAllAsync<T>(string orderProperty = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            if (orderProperty == null)
            {
                return await context.Set<T>().ToListAsync();
            }

            var properties = typeof(T).GetProperties().Select(c => c.Name);

            if (!properties.Contains(orderProperty))
            {
                throw new Exception("Not Find Property Exception");
            }

            return await context.Set<T>().OrderBy(c => c.GetType().GetProperties().First(p => p.Name == orderProperty))
                .ToListAsync();

        }
        public List<T> GetAllQuery<T>(string path, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).Include(path).ToList() : context.Set<T>().Include(path).ToList();
        }
        public List<T> GetAllQuery<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).ToList() : context.Set<T>().ToList();

        }

        public async Task<List<T>> GetAllQueryAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).ToListAsync()
                : context.Set<T>().ToListAsync());

        }

        public int GetCount<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null
                ? context.Set<T>().Where(whereLambda).Count()
                : context.Set<T>().Count();
        }
        public async Task<int> GetCountAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).CountAsync()
                : context.Set<T>().CountAsync());
        }

        public bool GetAny<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            using var context = GetCurrentDbContext();
            return whereLambda != null ? context.Set<T>().Where(whereLambda).Any() : context.Set<T>().Any();
        }

        public async Task<bool> GetAnyAsync<T>(Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            return await (whereLambda != null
                ? context.Set<T>().Where(whereLambda).AnyAsync()
                : context.Set<T>().AnyAsync());
        }

        public List<T> Pagination<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy,
            Expression<Func<T, bool>> whereLambda = null, bool isOrder = true) where T : class
        {
            using var context = GetCurrentDbContext();
            IQueryable<T> queryList =
                isOrder ? context.Set<T>().OrderBy(orderBy) : context.Set<T>().OrderByDescending(orderBy);

            if (whereLambda != null)
            {
                queryList = queryList.Where(whereLambda);
            }

            return queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        }

        public async Task<List<T>> PaginationAsync<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy,
            Expression<Func<T, bool>> whereLambda = null, bool isOrder = true) where T : class
        {
            await using var context = GetCurrentDbContext();
            IQueryable<T> queryList =
                isOrder ? context.Set<T>().OrderBy(orderBy) : context.Set<T>().OrderByDescending(orderBy);

            if (whereLambda != null)
            {
                queryList = queryList.Where(whereLambda);
            }

            return await queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();
        }

        public List<T> Pagination<T>(int pageIndex, int pageSize, string ordering, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            var ditProList = new Dictionary<string, PropertyInfo>();
            using var context = GetCurrentDbContext();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            proInfos.ForEach(p => { ditProList.Add(p.Name, p); });

            //分页的时候一定要注意 Order 一定在Skip 之前
            var queryList = context.Set<T>()
                .OrderBy(c => c.GetType().GetProperties().First(p => p.Name == ordering).Name);
            if (whereLambda != null)
            {
                queryList = (IOrderedQueryable<T>)queryList.Where(whereLambda);
            }

            return queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        }

        public async Task<List<T>> PaginationAsync<T>(int pageIndex, int pageSize, string ordering, Expression<Func<T, bool>> whereLambda = null) where T : class
        {
            await using var context = GetCurrentDbContext();
            var t = typeof(T);
            var proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            var ditProList = new Dictionary<string, PropertyInfo>();
            proInfos.ForEach(p => { ditProList.Add(p.Name, p); });

            //分页的时候一定要注意 Order 一定在Skip 之前
            var queryList = context.Set<T>()
                .OrderBy(c => c.GetType().GetProperties().First(p => p.Name == ordering).Name);
            if (whereLambda != null)
            {
                queryList = (IOrderedQueryable<T>)queryList.Where(whereLambda);
            }

            return await queryList.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();
        }

        public List<T> GetSelect<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            using var context = GetCurrentDbContext();
            return context.Set<T>().Where(whereLambda).ToList();
        }

        public List<T> QueryPro<T>(string sql, List<SqlParameter> parameters, CommandType cmdType = CommandType.Text) where T : class
        {
            using var context = GetCurrentDbContext();
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            var array = parameters.ToArray();
            var sqlParams = array.Select(item => item).Cast<object>().ToList();
            //进行执行存储过程
            if (cmdType != CommandType.StoredProcedure)
                return context.Set<T>().FromSqlRaw(sql, sqlParams).ToList();


            var paraNames = new StringBuilder();
            foreach (var item in parameters)
            {
                paraNames.Append($" @{item},");
            }

            sql = paraNames.Length > 0 ? $"exec {sql} {paraNames.ToString().Trim(',')}" : $"exec {sql} ";
            return context.Set<T>().FromSqlRaw(sql, sqlParams).ToList();
        }

        public void RollBackChanges<T>() where T : class
        {
            using var context = GetCurrentDbContext();
            var query = context.ChangeTracker.Entries().ToList();
            query.ForEach(p => p.State = EntityState.Unchanged);
        }

        public bool Update<T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, T>> updateLambda) where T : class
        {
            throw new NotImplementedException();
        }

        public Task<bool> UpdateAsync<T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, T>> updateLambda) where T : class
        {
            throw new NotImplementedException();
        }
    }
}