using CloudBuilder.Core.Application.Builders; using Microsoft.AspNetCore.Http; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.Extensions.DependencyInjection; using System.Data; using System.Data.Common; using System.Linq.Expressions; namespace CloudBuilder.Core.DatabaseAccessor.Entity { public class Repository : IRepository where TEntity : class { private readonly CloudBuilderBuilder builder; private DbContext dbContext; private readonly IHttpContextAccessor httpContext; public Repository(IServiceProvider serviceProvider, [FromKeyedServices(MasterDbContext.MASTER_DB_CONTEXT)] DbContext dbContext, IUnitOfWork unitOfWork, IHttpContextAccessor httpContext) { this.httpContext = httpContext; this.dbContext = dbContext; this.UnitOfWork = unitOfWork; ServiceProvider = serviceProvider; Entities = this.dbContext.Set()!; DetachedEntities = Entities.AsNoTracking()!; } public IUnitOfWork UnitOfWork { get; set; } public DbContext GetDbContext() { return dbContext; } public DbSet Entities { get; set; } = null!; public IQueryable DetachedEntities { get; set; } = null!; public DbConnection DbConnection { get { return dbContext.Database.GetDbConnection(); } } public IServiceProvider ServiceProvider { get; set; } = null!; public virtual TRepository GetRepository() { return ServiceProvider.GetRequiredService(); } public void ChangeMasterDatabase() { this.dbContext = ServiceProvider.GetRequiredKeyedService(MasterDbContext.MASTER_DB_CONTEXT); Entities = this.dbContext.Set()!; DetachedEntities = Entities.AsNoTracking()!; } public void ChangeSecondaryDatabase() { this.dbContext = ServiceProvider.GetRequiredKeyedService(SecondaryDbContext.SECONDARY_DB_CONTEXT); Entities = this.dbContext.Set()!; DetachedEntities = Entities.AsNoTracking()!; } #region FromSqlRaw public virtual IQueryable FromSql(string sql, params object[] parameters) { if (parameters == null) return Entities.FromSqlRaw(sql); else return Entities.FromSqlRaw(sql, parameters); } public virtual IQueryable FromSqlWhere(TEntity t, string where, params object[] parameters) { string sql = $"{((IEntity)t).GetSelectFrom()} {where} "; if (parameters == null) return Entities.FromSqlRaw(sql); else return Entities.FromSqlRaw(sql, parameters); } public virtual TEntity[] FindBySql(string sql, params object[] parameters) { if (parameters == null) return Entities.FromSqlRaw(sql).ToArray(); else return Entities.FromSqlRaw(sql, parameters).ToArray(); } public virtual TEntity[] FindBySqlWhere(TEntity t, string where, params object[] parameters) { string sql = $"{((IGet)t).GetSelectFrom()} {where} "; if (parameters == null) return Entities.FromSqlRaw(sql).ToArray(); else return Entities.FromSqlRaw(sql, parameters).ToArray(); } public void PackSqlParameter(List parameters, string parameterName, object value) { if (parameters == null) parameters = new List(); else { string formatedValue; if (value == null) formatedValue = $"null"; else { formatedValue = $"'{value.ToString()}'"; if (value is DateTime && !string.IsNullOrEmpty(formatedValue)) formatedValue = $"'{Convert.ToDateTime(formatedValue).ToString("yyyy-MM-dd HH:mm:ss")}'"; } parameters.Add(new SqlParameter(parameterName, value == null ? DBNull.Value : value)); } } public virtual void ExecuteNonQuery(string sql, params object[] parameters) { var conn = dbContext.Database.GetDbConnection(); ; conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandText = sql; if (parameters != null && parameters.Length > 0) cmd.Parameters.AddRange(parameters); cmd.ExecuteNonQuery(); } public virtual object ExecuteScalar(string sql, params object[] parameters) { var conn = dbContext.Database.GetDbConnection(); ; conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandText = sql; if (parameters != null && parameters.Length > 0) cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } public virtual DataTable SelectDataTable(string sql, params object[] parameters) { var conn = dbContext.Database.GetDbConnection(); ; conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandText = sql; if (parameters != null && parameters.Length > 0) cmd.Parameters.AddRange(parameters); SqlDataAdapter da = new SqlDataAdapter(); da.SelectCommand = cmd as SqlCommand; DataTable dt = new DataTable(); da.Fill(dt); dt.TableName = "TableName"; return dt; } #endregion #region Insert public virtual EntityEntry Insert(TEntity entity) { var entryEntity = Entities.Add(entity); return entryEntity; } public virtual void Insert(params TEntity[] entities) { Entities.AddRange(entities); } public virtual void Insert(IEnumerable entities) { Entities.AddRange(entities); } public virtual async Task> InsertAsync(TEntity entity, CancellationToken cancellationToken = default) { var entityEntry = await Entities.AddAsync(entity, cancellationToken); return entityEntry; } public virtual Task InsertAsync(params TEntity[] entities) { return Entities.AddRangeAsync(entities); } public virtual Task InsertAsync(IEnumerable entities, CancellationToken cancellationToken = default) { return Entities.AddRangeAsync(entities, cancellationToken); } public virtual EntityEntry InsertNow(TEntity entity) { var entityEntry = Insert(entity); SaveNow(); return entityEntry; } /// /// 新增多条记录 /// /// 多个实体 public virtual void InsertNow(params TEntity[] entities) { Insert(entities); SaveNow(); } /// /// 新增多条记录 /// /// 多个实体 public virtual void InsertNow(IEnumerable entities) { Insert(entities); SaveNow(); } /// /// 新增一条记录并立即提交 /// /// 实体 /// /// 取消异步令牌 /// 数据库中返回的实体 public virtual async Task> InsertNowAsync(TEntity entity, CancellationToken cancellationToken = default) { var entityEntry = await InsertAsync(entity, cancellationToken); await SaveNowAsync(cancellationToken); return entityEntry; } /// /// 新增多条记录并立即提交 /// /// 多个实体 /// Task public virtual async Task InsertNowAsync(params TEntity[] entities) { await InsertAsync(entities); await SaveNowAsync(); } /// /// 新增多条记录并立即提交 /// /// 多个实体 /// 取消异步令牌 /// Task public virtual async Task InsertNowAsync(TEntity[] entities, CancellationToken cancellationToken = default) { await InsertAsync(entities); await SaveNowAsync(cancellationToken); } /// /// 新增多条记录并立即提交 /// /// 多个实体 /// 取消异步令牌 /// Task public virtual async Task InsertNowAsync(IEnumerable entities, CancellationToken cancellationToken = default) { await InsertAsync(entities, cancellationToken); await SaveNowAsync(cancellationToken); } /// /// 提交更改操作 /// /// public virtual int SaveNow() { return dbContext.SaveChanges(); } /// /// 提交更改操作(异步) /// /// /// public virtual Task SaveNowAsync(CancellationToken cancellationToken = default) { return dbContext.SaveChangesAsync(cancellationToken); } #endregion #region Update public virtual EntityEntry Update(TEntity entity) { var entityEntry = Entities.Update(entity); return entityEntry; } public virtual void Update(params TEntity[] entities) { Entities.UpdateRange(entities); } public virtual void Update(IEnumerable entities) { Entities.UpdateRange(entities); } public virtual Task> UpdateAsync(TEntity entity) { return Task.FromResult(Update(entity)); } public virtual Task UpdateAsync(params TEntity[] entities) { Update(entities); return Task.CompletedTask; } public virtual Task UpdateAsync(IEnumerable entities) { Update(entities); return Task.CompletedTask; } public virtual EntityEntry UpdateNow(TEntity entity) { var entityEntry = Update(entity); SaveNow(); return entityEntry; } public virtual void UpdateNow(params TEntity[] entities) { Update(entities); SaveNow(); } public virtual void UpdateNow(IEnumerable entities) { Update(entities); SaveNow(); } public virtual async Task> UpdateNowAsync(TEntity entity, CancellationToken cancellationToken = default) { var entityEntry = await UpdateAsync(entity); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task UpdateNowAsync(params TEntity[] entities) { await UpdateAsync(entities); await SaveNowAsync(); } public virtual async Task UpdateNowAsync(TEntity[] entities, CancellationToken cancellationToken = default) { await UpdateAsync(entities); await SaveNowAsync(cancellationToken); } public virtual async Task UpdateNowAsync(IEnumerable entities, CancellationToken cancellationToken = default) { await UpdateAsync(entities); await SaveNowAsync(cancellationToken); } public virtual EntityEntry UpdateInclude(TEntity entity, IEnumerable propertyNames) { var entityEntry = ChangeEntityState(entity, EntityState.Detached); foreach (var propertyName in propertyNames) { EntityPropertyEntry(entity, propertyName).IsModified = true; } return entityEntry; } public virtual EntityEntry UpdateInclude(TEntity entity, IEnumerable>> propertyPredicates) { var entityEntry = ChangeEntityState(entity, EntityState.Detached); foreach (var propertyPredicate in propertyPredicates) { EntityPropertyEntry(entity, propertyPredicate).IsModified = true; } return entityEntry; } public virtual Task> UpdateIncludeAsync(TEntity entity, string[] propertyNames) { return Task.FromResult(UpdateInclude(entity, propertyNames)); } public virtual Task> UpdateIncludeAsync(TEntity entity, Expression>[] propertyPredicates) { return Task.FromResult(UpdateInclude(entity, propertyPredicates)); } public virtual Task> UpdateIncludeAsync(TEntity entity, IEnumerable propertyNames) { return Task.FromResult(UpdateInclude(entity, propertyNames)); } public virtual Task> UpdateIncludeAsync(TEntity entity, IEnumerable>> propertyPredicates) { return Task.FromResult(UpdateInclude(entity, propertyPredicates)); } public virtual EntityEntry UpdateIncludeNow(TEntity entity, string[] propertyNames) { var entityEntry = UpdateInclude(entity, propertyNames); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateIncludeNow(TEntity entity, Expression>[] propertyPredicates) { var entityEntry = UpdateInclude(entity, propertyPredicates); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateIncludeNow(TEntity entity, IEnumerable propertyNames) { var entityEntry = UpdateInclude(entity, propertyNames); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateIncludeNow(TEntity entity, IEnumerable>> propertyPredicates) { var entityEntry = UpdateInclude(entity, propertyPredicates); SaveNow(); return entityEntry; } public virtual async Task> UpdateIncludeNowAsync(TEntity entity, string[] propertyNames, CancellationToken cancellationToken = default) { var entityEntry = await UpdateIncludeAsync(entity, propertyNames); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateIncludeNowAsync(TEntity entity, Expression>[] propertyPredicates, CancellationToken cancellationToken = default) { var entityEntry = await UpdateIncludeAsync(entity, propertyPredicates); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateIncludeNowAsync(TEntity entity, IEnumerable propertyNames, CancellationToken cancellationToken = default) { var entityEntry = await UpdateIncludeAsync(entity, propertyNames); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateIncludeNowAsync(TEntity entity, IEnumerable>> propertyPredicates, CancellationToken cancellationToken = default) { var entityEntry = await UpdateIncludeAsync(entity, propertyPredicates); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual EntityEntry UpdateExclude(TEntity entity, IEnumerable propertyNames) { var entityEntry = ChangeEntityState(entity, EntityState.Modified); foreach (var propertyName in propertyNames) { EntityPropertyEntry(entity, propertyName).IsModified = false; } return entityEntry; } public virtual EntityEntry UpdateExclude(TEntity entity, IEnumerable>> propertyPredicates) { var entityEntry = ChangeEntityState(entity, EntityState.Modified); foreach (var propertyPredicate in propertyPredicates) { EntityPropertyEntry(entity, propertyPredicate).IsModified = false; } return entityEntry; } public virtual Task> UpdateExcludeAsync(TEntity entity, string[] propertyNames) { return Task.FromResult(UpdateExclude(entity, propertyNames)); } public virtual Task> UpdateExcludeAsync(TEntity entity, Expression>[] propertyPredicates) { return Task.FromResult(UpdateExclude(entity, propertyPredicates)); } public virtual Task> UpdateExcludeAsync(TEntity entity, IEnumerable propertyNames) { return Task.FromResult(UpdateExclude(entity, propertyNames)); } public virtual Task> UpdateExcludeAsync(TEntity entity, IEnumerable>> propertyPredicates) { return Task.FromResult(UpdateExclude(entity, propertyPredicates)); } public virtual EntityEntry UpdateExcludeNow(TEntity entity, string[] propertyNames) { var entityEntry = UpdateExclude(entity, propertyNames); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateExcludeNow(TEntity entity, Expression>[] propertyPredicates) { var entityEntry = UpdateExclude(entity, propertyPredicates); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateExcludeNow(TEntity entity, IEnumerable propertyNames) { var entityEntry = UpdateExclude(entity, propertyNames); SaveNow(); return entityEntry; } public virtual EntityEntry UpdateExcludeNow(TEntity entity, IEnumerable>> propertyPredicates) { var entityEntry = UpdateExclude(entity, propertyPredicates); SaveNow(); return entityEntry; } public virtual async Task> UpdateExcludeNowAsync(TEntity entity, string[] propertyNames, CancellationToken cancellationToken = default) { var entityEntry = await UpdateExcludeAsync(entity, propertyNames); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateExcludeNowAsync(TEntity entity, Expression>[] propertyPredicates, CancellationToken cancellationToken = default) { var entityEntry = await UpdateExcludeAsync(entity, propertyPredicates); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateExcludeNowAsync(TEntity entity, IEnumerable propertyNames, CancellationToken cancellationToken = default) { var entityEntry = await UpdateExcludeAsync(entity, propertyNames); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task> UpdateExcludeNowAsync(TEntity entity, IEnumerable>> propertyPredicates, CancellationToken cancellationToken = default) { var entityEntry = await UpdateExcludeAsync(entity, propertyPredicates); await SaveNowAsync(cancellationToken); return entityEntry; } #endregion #region Delete public virtual EntityEntry Delete(TEntity entity) { return Entities.Remove(entity); } public virtual void Delete(params TEntity[] entities) { Entities.RemoveRange(entities); } public virtual void Delete(IEnumerable entities) { Entities.RemoveRange(entities); } public virtual Task> DeleteAsync(TEntity entity) { return Task.FromResult(Delete(entity)); } public virtual Task DeleteAsync(params TEntity[] entities) { Delete(entities); return Task.CompletedTask; } public virtual Task DeleteAsync(IEnumerable entities) { Delete(entities); return Task.CompletedTask; } public virtual EntityEntry DeleteNow(TEntity entity) { var entityEntry = Delete(entity); SaveNow(); return entityEntry; } public virtual void DeleteNow(params TEntity[] entities) { Delete(entities); SaveNow(); } public virtual void DeleteNow(IEnumerable entities) { Delete(entities); SaveNow(); } public virtual async Task> DeleteNowAsync(TEntity entity, CancellationToken cancellationToken = default) { var entityEntry = await DeleteAsync(entity); await SaveNowAsync(cancellationToken); return entityEntry; } public virtual async Task DeleteNowAsync(params TEntity[] entities) { await DeleteAsync(entities); await SaveNowAsync(); } public virtual async Task DeleteNowAsync(TEntity[] entities, CancellationToken cancellationToken = default) { await DeleteAsync(entities); await SaveNowAsync(cancellationToken); } public virtual async Task DeleteNowAsync(IEnumerable entities, CancellationToken cancellationToken = default) { await DeleteAsync(entities); await SaveNowAsync(cancellationToken); } #endregion #region EntityEntry /// /// 将实体加入数据上下文托管 /// /// 实体 /// EntityEntry public virtual EntityEntry Entry(object entity) { return dbContext.Entry(entity); } /// /// 将实体加入数据上下文托管 /// /// 实体 /// public virtual EntityEntry Entry(TEntity entity) { return dbContext.Entry(entity); } /// /// 获取实体状态 /// /// 实体 /// public virtual EntityState EntityEntryState(object entity) { return Entry(entity).State; } /// /// 获取实体状态 /// /// 实体 /// EntityState public virtual EntityState EntityEntryState(TEntity entity) { return Entry(entity).State; } /// /// 将实体属性加入托管 /// /// 实体 /// 属性名 /// PropertyEntry public virtual PropertyEntry EntityPropertyEntry(object entity, string propertyName) { return Entry(entity).Property(propertyName); } /// /// 将实体属性加入托管 /// /// 实体 /// 属性名 /// PropertyEntry public virtual PropertyEntry EntityPropertyEntry(TEntity entity, string propertyName) { return Entry(entity).Property(propertyName); } /// /// 将实体属性加入托管 /// /// 属性类型 /// 实体 /// 属性表达式 /// PropertyEntry public virtual PropertyEntry EntityPropertyEntry(TEntity entity, Expression> propertyPredicate) { return Entry(entity).Property(propertyPredicate); } /// /// 改变实体状态 /// /// 实体 /// 实体状态 /// EntityEntry public virtual EntityEntry ChangeEntityState(object entity, EntityState entityState) { var entityEntry = Entry(entity); entityEntry.State = entityState; return entityEntry; } /// /// 改变实体状态 /// /// 实体 /// 实体状态 /// EntityEntry{TEntity} public virtual EntityEntry ChangeEntityState(TEntity entity, EntityState entityState) { var entityEntry = Entry(entity); entityEntry.State = entityState; return entityEntry; } /// /// 改变实体状态 /// /// 实体条目 /// 实体状态 /// EntityEntry public virtual EntityEntry ChangeEntityState(EntityEntry entityEntry, EntityState entityState) { entityEntry.State = entityState; return entityEntry; } /// /// 改变实体状态 /// /// 实体条目 /// 实体状态 /// EntityEntry{TEntity} public virtual EntityEntry ChangeEntityState(EntityEntry entityEntry, EntityState entityState) { entityEntry.State = entityState; return entityEntry; } /// /// 判断是否被附加 /// /// 实体 /// bool public virtual bool IsAttached(object entity) { return EntityEntryState(entity) != EntityState.Detached; } /// /// 判断是否被附加 /// /// 实体 /// bool public virtual bool IsAttached(TEntity entity) { return EntityEntryState(entity) != EntityState.Detached; } /// /// 附加实体 /// /// 实体 /// EntityEntry public virtual EntityEntry Attach(object entity) { return dbContext.Attach(entity); } /// /// 附加实体 /// /// 实体 /// EntityEntry public virtual EntityEntry Attach(TEntity entity) { return dbContext.Attach(entity); } /// /// 附加多个实体 /// /// 多个实体 public virtual void AttachRange(params object[] entities) { dbContext.AttachRange(entities); } /// /// 附加多个实体 /// /// 多个实体 public virtual void AttachRange(IEnumerable entities) { dbContext.AttachRange(entities); } /// /// 取消附加实体 /// /// 实体 public virtual void Detach(object entity) { ChangeEntityState(entity, EntityState.Detached); } /// /// 取消附加实体 /// /// 实体 public virtual void Detach(TEntity entity) { ChangeEntityState(entity, EntityState.Detached); } /// /// 取消附加实体 /// /// 实体条目 public virtual void Detach(EntityEntry entityEntry) { ChangeEntityState(entityEntry, EntityState.Detached); } /// /// 取消附加实体 /// /// 实体条目 public virtual void Detach(EntityEntry entityEntry) { ChangeEntityState(entityEntry, EntityState.Detached); } #endregion } }