using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; using VOL.Core.Dapper; using VOL.Core.DBManager; using VOL.Core.EFDbContext; using VOL.Core.Enums; using VOL.Core.Extensions; using VOL.Core.Utilities; using VOL.Entity; using VOL.Entity.SystemModels; namespace VOL.Core.BaseProvider { public abstract class RepositoryBase where TEntity : BaseEntity { public RepositoryBase() { } public RepositoryBase(BaseDbContext dbContext) { this.DefaultDbContext = dbContext ?? throw new Exception("dbContext未实例化。"); } private BaseDbContext DefaultDbContext { get; set; } private BaseDbContext EFContext { get { // DBServerProvider.GetDbContextConnection(DefaultDbContext); return DefaultDbContext; } } public virtual BaseDbContext DbContext { get { return DefaultDbContext; } } private DbSet DBSet { get { return EFContext.Set(); } } public ISqlDapper DapperContext { get { return DBServerProvider.GetSqlDapper(); } } /// /// 执行事务 /// /// 如果返回false则回滚事务(可自行定义规则) /// public virtual WebResponseContent DbContextBeginTransaction(Func action) { WebResponseContent webResponse = new WebResponseContent(); using (IDbContextTransaction transaction = DefaultDbContext.Database.BeginTransaction()) { try { webResponse = action(); if (webResponse.Status) { transaction.Commit(); } else { transaction.Rollback(); } return webResponse; } catch (Exception ex) { transaction.Rollback(); return new WebResponseContent().Error(ex.Message); } } } public virtual bool Exists(Expression> predicate) where TExists : class { return EFContext.Set().Any(predicate); } public virtual Task ExistsAsync(Expression> predicate) where TExists : class { return EFContext.Set().AnyAsync(predicate); } public virtual bool Exists(Expression> predicate) { return DBSet.Any(predicate); } public virtual Task ExistsAsync(Expression> predicate) { return DBSet.AnyAsync(predicate); } public virtual List Find(Expression> predicate) where TFind : class { return EFContext.Set().Where(predicate).ToList(); } public virtual Task FindAsyncFirst(Expression> predicate) where TFind : class { return FindAsIQueryable(predicate).FirstOrDefaultAsync(); } public virtual Task FindAsyncFirst(Expression> predicate) { return FindAsIQueryable(predicate).FirstOrDefaultAsync(); } public virtual Task> FindAsync(Expression> predicate) where TFind : class { return FindAsIQueryable(predicate).ToListAsync(); } public virtual Task> FindAsync(Expression> predicate) { return FindAsIQueryable(predicate).ToListAsync(); } public virtual Task FindFirstAsync(Expression> predicate) { return FindAsIQueryable(predicate).FirstOrDefaultAsync(); } public virtual Task> FindAsync(Expression> predicate, Expression> selector) { return FindAsIQueryable(predicate).Select(selector).ToListAsync(); } public virtual Task FindFirstAsync(Expression> predicate, Expression> selector) { return FindAsIQueryable(predicate).Select(selector).FirstOrDefaultAsync(); } public virtual IQueryable FindAsIQueryable(Expression> predicate) where TFind : class { return EFContext.Set().Where(predicate); } public virtual List Find(IEnumerable sources, Func>> predicate) where Source : class { return FindAsIQueryable(sources, predicate).ToList(); } public virtual List Find(IEnumerable sources, Func>> predicate, Expression> selector) where Source : class { return FindAsIQueryable(sources, predicate).Select(selector).ToList(); } /// /// 多条件查询 /// /// /// /// /// public virtual IQueryable FindAsIQueryable(IEnumerable sources, Func>> predicate) where Source : class { // EFContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll; Expression> resultPredicate = x => 1 == 2; foreach (Source source in sources) { Expression> expression = predicate(source); resultPredicate = (resultPredicate).Or((expression)); } return EFContext.Set().Where(resultPredicate); } public virtual List Find(Expression> predicate, Expression> selector) { return DBSet.Where(predicate).Select(selector).ToList(); } /// /// 单表查询 /// /// /// public virtual List Find(Expression> predicate) { return FindAsIQueryable(predicate).ToList(); } /// /// /// /// /// /// 排序字段 /// public virtual TEntity FindFirst(Expression> predicate, Expression>> orderBy = null) { return FindAsIQueryable(predicate, orderBy).FirstOrDefault(); } public IQueryable FindAsIQueryable(Expression> predicate, Expression>> orderBy = null) { if (orderBy != null) return DbContext.Set().Where(predicate).GetIQueryableOrderBy(orderBy.GetExpressionToDic()); return DbContext.Set().Where(predicate); } public IIncludableQueryable Include(Expression> incluedProperty) { return DbContext.Set().Include(incluedProperty); } /// /// 通过条件查询返回指定列的数据(将TEntity映射到匿名或实体T) ///var result = Sys_UserRepository.GetInstance.Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName }); /// /// /// /// /// /// /// /// 查询条件 /// 多个排序字段key为字段,value为升序/降序 /// public virtual IQueryable IQueryablePage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true) where TFind : class { pageIndex = pageIndex <= 0 ? 1 : pageIndex; pagesize = pagesize <= 0 ? 10 : pagesize; if (predicate == null) { predicate = x => 1 == 1; } var _db = DbContext.Set(); rowcount = returnRowCount ? _db.Count(predicate) : 0; return DbContext.Set().Where(predicate) .GetIQueryableOrderBy(orderBy.GetExpressionToDic()) .Skip((pageIndex - 1) * pagesize) .Take(pagesize); } /// /// 分页排序 /// /// /// /// /// /// /// public virtual IQueryable IQueryablePage(IQueryable queryable, int pageIndex, int pagesize, out int rowcount, Dictionary orderBy, bool returnRowCount = true) { pageIndex = pageIndex <= 0 ? 1 : pageIndex; pagesize = pagesize <= 0 ? 10 : pagesize; rowcount = returnRowCount ? queryable.Count() : 0; return queryable.GetIQueryableOrderBy(orderBy) .Skip((pageIndex - 1) * pagesize) .Take(pagesize); } public virtual List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, Expression> selectorResult, bool returnRowCount = true) { return IQueryablePage(pageIndex, pagesize, out rowcount, predicate, orderBy, returnRowCount).Select(selectorResult).ToList(); } public List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true) { return IQueryablePage(pageIndex, pagesize, out rowcount, predicate, orderBy).ToList(); } public virtual List QueryByPage(int pageIndex, int pagesize, Expression> predicate, Expression>> orderBy, Expression> selectorResult = null) { return IQueryablePage(pageIndex, pagesize, out int rowcount, predicate, orderBy).Select(selectorResult).ToList(); } /// /// 更新表数据 /// /// /// 是否保存 /// 格式 Expression> expTree = x => new { x.字段1, x.字段2 }; public virtual int Update(TEntity entity, Expression> properties, bool saveChanges = false) { return Update(entity, properties, saveChanges); } public virtual int Update(TSource entity, Expression> properties, bool saveChanges = false) where TSource : class { return UpdateRange(new List { entity }, properties, saveChanges); } public virtual int Update(TSource entity, string[] properties, bool saveChanges = false) where TSource : class { return UpdateRange(new List() { entity }, properties, saveChanges); } public virtual int Update(TSource entity, bool saveChanges = false) where TSource : class { return UpdateRange(new List() { entity }, new string[0], saveChanges); } public virtual int UpdateRange(IEnumerable entities, Expression> properties, bool saveChanges = false) where TSource : class { return UpdateRange(entities, properties?.GetExpressionProperty(), saveChanges); } public virtual int UpdateRange(IEnumerable entities, bool saveChanges = false) where TSource : class { return UpdateRange(entities, new string[0], saveChanges); } /// /// 更新表数据 /// /// /// 格式 Expression> expTree = x => new { x.字段1, x.字段2 }; public int UpdateRange(IEnumerable entities, string[] properties, bool saveChanges = false) where TSource : class { if (properties != null && properties.Length > 0) { PropertyInfo[] entityProperty = typeof(TSource).GetProperties(); string keyName = entityProperty.GetKeyName(); if (properties.Contains(keyName)) { properties = properties.Where(x => x != keyName).ToArray(); } properties = properties.Where(x => entityProperty.Select(s => s.Name).Contains(x)).ToArray(); } foreach (TSource item in entities) { if (properties == null || properties.Length == 0) { DbContext.Entry(item).State = EntityState.Modified; continue; } var entry = DbContext.Entry(item); properties.ToList().ForEach(x => { entry.Property(x).IsModified = true; }); } if (!saveChanges) return 0; //2020.04.24增加更新时并行重试处理 try { // Attempt to save changes to the database return DbContext.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { int affectedRows = 0; foreach (var entry in ex.Entries) { var proposedValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); //databaseValues == null说明数据已被删除 if (databaseValues != null) { foreach (var property in properties == null || properties.Length == 0 ? proposedValues.Properties : proposedValues.Properties.Where(x => properties.Contains(x.Name))) { var proposedValue = proposedValues[property]; var databaseValue = databaseValues[property]; } affectedRows++; entry.OriginalValues.SetValues(databaseValues); } } if (affectedRows == 0) return 0; return DbContext.SaveChanges(); } } /// /// /// /// /// 是否修改明细 /// 是否删除明细不存在的数据 /// 主表指定修改字段 /// 明细指定修改字段 /// 是否保存 /// public virtual WebResponseContent UpdateRange(TEntity entity, bool updateDetail = false, bool delNotExist = false, Expression> updateMainFields = null, Expression> updateDetailFields = null, bool saveChange = false) where Detail : class { WebResponseContent webResponse = new WebResponseContent(); Update(entity, updateMainFields); string message = ""; if (updateDetail) { PropertyInfo[] properties = typeof(TEntity).GetProperties(); PropertyInfo detail = properties.Where(x => x.PropertyType.Name == "List`1").ToList().FirstOrDefault(); if (detail != null) { PropertyInfo key = properties.GetKeyProperty(); object obj = detail.GetValue(entity); Type detailType = typeof(TEntity).GetCustomAttribute().DetailTable[0]; message = UpdateDetail(obj as List, key.Name, key.GetValue(entity), updateDetailFields, delNotExist); } } if (!saveChange) return webResponse.OK(); DbContext.SaveChanges(); return webResponse.OK("修改成功,明细" + message, entity); } private string UpdateDetail(List list, string keyName, object keyValue, Expression> updateDetailFields = null, bool delNotExist = false) where TDetail : class { if (list == null) return ""; PropertyInfo property = typeof(TDetail).GetKeyProperty(); string detailKeyName = property.Name; DbSet details = DbContext.Set(); Expression> selectExpression = detailKeyName.GetExpression(); Expression> whereExpression = keyName.CreateExpression(keyValue, LinqExpressionType.Equal); List detailKeys = details.Where(whereExpression).Select(selectExpression).ToList(); //获取主键默认值 string keyDefaultVal = property.PropertyType .Assembly .CreateInstance(property.PropertyType.FullName).ToString(); int addCount = 0; int editCount = 0; int delCount = 0; PropertyInfo mainKeyProperty = typeof(TDetail).GetProperty(keyName); List keys = new List(); list.ForEach(x => { var set = DbContext.Set(); object val = property.GetValue(x); //主键是默认值的为新增的数据 if (val.ToString() == keyDefaultVal) { x.SetCreateDefaultVal(); //设置主表的值,也可以不设置 mainKeyProperty.SetValue(x, keyValue); details.Add(x); addCount++; } else//修改的数据 { //获取所有修改的key,如果从数据库查来的key,不在修改中的key,则为删除的数据 keys.Add(val); x.SetModifyDefaultVal(); Update(x, updateDetailFields); // repository.DbContext.Entry(x).State = EntityState.Modified; editCount++; } }); //删除 if (delNotExist) { detailKeys.Where(x => !keys.Contains(x)).ToList().ForEach(d => { delCount++; TDetail detail = Activator.CreateInstance(); property.SetValue(detail, d); DbContext.Entry(detail).State = EntityState.Deleted; for (int i = 0; i < list.Count(); i++) { if (property.GetValue(list[i]) == d) { list.RemoveAt(i); } } }); } return $"修改[{editCount}]条,新增[{addCount}]条,删除[{delCount}]条"; } public virtual void Delete(TEntity model, bool saveChanges) { DBSet.Remove(model); if (saveChanges) { DbContext.SaveChanges(); } } /// /// 通过主键批量删除 /// /// 主键key /// 是否连明细一起删除 /// public virtual int DeleteWithKeys(object[] keys, bool delList = false) { Type entityType = typeof(TEntity); string tKey = entityType.GetKeyProperty().Name; FieldType fieldType = entityType.GetFieldType(); string joinKeys = (fieldType == FieldType.Int || fieldType == FieldType.BigInt) ? string.Join(",", keys) : $"'{string.Join("','", keys)}'"; string sql = $"DELETE FROM {entityType.GetEntityTableName() } where {tKey} in ({joinKeys});"; if (delList) { Type detailType = entityType.GetCustomAttribute().DetailTable?[0]; if (detailType != null) sql = sql + $"DELETE FROM {detailType.GetEntityTableName()} where {tKey} in ({joinKeys});"; } return ExecuteSqlCommand(sql); } public virtual Task AddAsync(TEntity entities) { return DBSet.AddRangeAsync(entities); } public virtual Task AddRangeAsync(IEnumerable entities) { return DBSet.AddRangeAsync(entities); } public virtual void Add(TEntity entities, bool saveChanges = false) { AddRange(new List() { entities }, saveChanges); } public virtual void AddRange(IEnumerable entities, bool saveChanges = false) { DBSet.AddRange(entities); if (saveChanges) DbContext.SaveChanges(); } public virtual void AddRange(IEnumerable entities, bool saveChanges = false) where T : class { DbContext.Set().AddRange(entities); if (saveChanges) DbContext.SaveChanges(); } /// /// 注意List生成的table的列顺序必须要和数据库表的列顺序一致 /// /// /// public virtual void BulkInsert(IEnumerable entities, bool setOutputIdentity = false) { // EFContext.Model.FindEntityType("").Relational() //Pomelo.EntityFrameworkCore.MySql try { // EFContext.BulkInsert(entities.ToList()); } catch (DbUpdateException ex) { throw (ex.InnerException as Exception ?? ex); } // BulkInsert(entities.ToDataTable(), typeof(T).GetEntityTableName(), null); } public virtual int SaveChanges() { return EFContext.SaveChanges(); } public virtual Task SaveChangesAsync() { return EFContext.SaveChangesAsync(); } public virtual int ExecuteSqlCommand(string sql, params SqlParameter[] sqlParameters) { return DbContext.Database.ExecuteSqlRaw(sql, sqlParameters); } public virtual List FromSql(string sql, params SqlParameter[] sqlParameters) { return DBSet.FromSqlRaw(sql, sqlParameters).ToList(); } /// /// 执行sql /// 使用方式 FormattableString sql=$"select * from xx where name ={xx} and pwd={xx1} ", /// FromSqlInterpolated内部处理sql注入的问题,直接在{xx}写对应的值即可 /// 注意:sql必须 select * 返回所有TEntity字段, /// /// /// public virtual IQueryable FromSqlInterpolated([NotNull] FormattableString sql) { //DBSet.FromSqlInterpolated(sql).Select(x => new { x,xxx}).ToList(); return DBSet.FromSqlInterpolated(sql); } /// /// 取消上下文跟踪 /// /// public virtual void Detached(TEntity entity) { DbContext.Entry(entity).State = EntityState.Detached; } public virtual void DetachedRange(IEnumerable entities) { foreach (var entity in entities) { DbContext.Entry(entity).State = EntityState.Detached; } } } }