using HRD.WebApi.DAL; using HRD.WebApi.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; namespace HRD.WebApi.Repositories { public abstract class BaseRepositoryCore : IBaseRepository where T : BaseEntityCore { protected readonly ILogger _logger; protected DbContext RepositoryContext { get; private set; } protected BaseRepositoryCore(WebApiBaseContext repositoryContext, ILogger logger) { RepositoryContext = repositoryContext; _logger = logger; } public virtual bool Add(T entity, bool saveEntity = true) { try { this.RepositoryContext.Set().Add(entity); if (saveEntity) { return this.SaveChanges(); } return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name + " " + entity?.EntityInfo()); return false; } } public virtual async Task AddAsync(T entity, bool saveEntity = true) { try { await this.RepositoryContext.Set().AddAsync(entity); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name + " " + entity?.EntityInfo()); return false; } } public virtual async Task AddListAsync(List list, bool saveEntity = true) { try { await this.RepositoryContext.Set().AddRangeAsync(list).ConfigureAwait(false); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual bool Delete(T entity) { try { this.RepositoryContext.Set().Remove(entity); return this.SaveChanges(); } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual async Task DeleteAsync(T entity, bool saveEntity = true) { try { this.RepositoryContext.Set().Remove(entity); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual async Task DeleteByIdAsync(int id, bool saveEntity = true) { try { var entity = await GetByIdAsync(id).ConfigureAwait(false); this.RepositoryContext.Set().Remove(entity); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual async Task DeleteFromTableAsync(string tablename, string whereClause = "") { string sql = $"DELETE FROM {tablename}"; if (!string.IsNullOrEmpty(whereClause)) sql += $" WHERE {whereClause}"; try { int count = await RepositoryContext.Database.ExecuteSqlRawAsync(sql).ConfigureAwait(false); return true; } catch (Exception ex) { WriteLogException(ex, $"sql: {sql}"); } return false; } public virtual bool Detach(T entity, bool saveChanges = true) { try { this.RepositoryContext.Entry(entity).State = EntityState.Detached; if (saveChanges) { return this.SaveChanges(); } return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual async Task DetachAsync(T entity, bool saveChanges = true) { try { this.RepositoryContext.Entry(entity).State = EntityState.Detached; if (saveChanges) { return await this.SaveChangesAsync(); } return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public virtual async Task ExecSQLQueryAsync(string sql) { try { var result = await RepositoryContext.Database.ExecuteSqlRawAsync($"{sql}").ConfigureAwait(false); return true; } catch (Exception ex) { WriteLogException(ex, $"{nameof(ExecSQLQueryAsync)} for '{sql}' Exception was thrown"); } return false; } public virtual async Task ExecStoredProcedureAsync(string storedProcedureName, string param = "") { try { var x = RepositoryContext.Database.IsSqlServer(); //var RepositoryContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext; if (string.IsNullOrEmpty(param)) { await RepositoryContext.Database.ExecuteSqlRawAsync($"exec {storedProcedureName} ").ConfigureAwait(false); } else { await RepositoryContext.Database.ExecuteSqlRawAsync($"exec {storedProcedureName} {param}").ConfigureAwait(false); } return true; } catch (Exception ex) { WriteLogException(ex, $"storedProcedureName: {storedProcedureName}; param: {param}"); } return false; } public virtual List GetAll(bool asNoTracking = true) { try { if (asNoTracking) { return this.RepositoryContext.Set().AsNoTracking().ToList(); } else { return this.RepositoryContext.Set().ToList(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual List TakeList(int count, bool asNoTracking = true) { try { if (asNoTracking) { return this.RepositoryContext.Set().AsNoTracking().Take(count).ToList(); } else { return this.RepositoryContext.Set().Take(count).ToList(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public async Task> TakePagesListAsync(int pageNumber, int pageSize, bool asNoTracking = true) { try { if (asNoTracking) { return await RepositoryContext .Set() .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .AsNoTracking() .ToListAsync(); } else { return await RepositoryContext .Set() .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual async Task> TakeListAsync(int count, bool asNoTracking = true) { try { if (asNoTracking) { return await this.RepositoryContext.Set().AsNoTracking().Take(count).ToListAsync(); } else { return await this.RepositoryContext.Set().Take(count).ToListAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual async Task> GetAllAsync(bool asNoTracking = true) { try { if (asNoTracking) { return await this.RepositoryContext.Set().AsNoTracking().ToListAsync(); } else { return await this.RepositoryContext.Set().ToListAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual List GetBy(Expression> expression, bool asNoTracking = true) { try { if (asNoTracking) { return this.RepositoryContext.Set().Where(expression).AsNoTracking().ToList(); ; } else { return this.RepositoryContext.Set().Where(expression).ToList(); ; } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual async Task GetByAsync(Expression> expression, bool asNoTracking = true) { try { if (asNoTracking) { return await this.RepositoryContext.Set().Where(expression).AsNoTracking().FirstOrDefaultAsync(); } else { return await this.RepositoryContext.Set().Where(expression).FirstOrDefaultAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual async Task GetByIdAsync(int entityId, bool asNoTracking = false) { try { /* if (entityId == default) { var items = await this.RepositoryContext.Set().Take(1).ToListAsync(); entityId = items[0].GetEntityId(); } */ var entity = await this.RepositoryContext.Set().FindAsync(entityId); if (asNoTracking) { this.RepositoryContext.Entry(entity).State = EntityState.Detached; } return entity; } catch (Exception ex) { WriteLogException(ex, $"{typeof(T).Name} id:{entityId}"); return default(T); } } public virtual async Task GetBySqlAsync(string sql, bool asNoTracking = true) { // return await this.RepositoryContext.Set().FromSqlInterpolated($"{apiFilter.ToString()}").AsNoTracking().ToListAsync(); try { return await this.RepositoryContext.Set().FromSqlInterpolated($"{sql}").AsNoTracking().FirstOrDefaultAsync(); } catch (Exception ex) { WriteLogException(ex, $"sql: {sql}"); return default; } } public virtual async Task GetByWithIncludeAsync(Expression> expression, string navigationPropertyPath, bool asNoTracking = true) { try { if (asNoTracking) { return await this.RepositoryContext.Set() .Where(expression) .Include(navigationPropertyPath) .AsNoTracking() .FirstOrDefaultAsync(); } else { return await this.RepositoryContext.Set() .Where(expression) .Include(navigationPropertyPath) .FirstOrDefaultAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return default; } } public virtual async Task> GetListByAsync(Expression> expression, bool asNoTracking = true) { try { if (asNoTracking) { return await this.RepositoryContext.Set().AsNoTracking().Where(expression).ToListAsync(); } else { return await this.RepositoryContext.Set().Where(expression).ToListAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); } return default; } public virtual async Task> TakeListByAsync(int count, Expression> expression, bool asNoTracking = true) { if (count == 0) return await GetListByAsync(expression, asNoTracking); var list = new List(); try { if (asNoTracking) { return await this.RepositoryContext.Set().AsNoTracking().Where(expression).Take(count).ToListAsync(); } else { return await this.RepositoryContext.Set().Where(expression).Take(count).ToListAsync(); } } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); } return list; } public virtual async Task> GetListByConditionFromSqlAsync(string sql) { // https://software-security.sans.org/developer-how-to/fix-sql-injection-microsoft-.net-with-parameterized-queries try { return await this.RepositoryContext.Set().FromSqlInterpolated($"{sql}").AsNoTracking().ToListAsync(); } catch (Exception ex) { WriteLogException(ex, $"sql:{sql}"); return default; } } public virtual async Task> GetListByConditionFromSqlRawAsync(string sql) { try { return await this.RepositoryContext.Set().FromSqlRaw(sql).AsNoTracking().ToListAsync(); } catch (Exception ex) { WriteLogException(ex, $"sql:{sql}"); return default; } } public string GetTableName() { return AttributeReader.GetTableName(RepositoryContext); } public virtual bool SaveChanges() { try { this.RepositoryContext.SaveChanges(); return true; } catch (Exception ex) { WriteLogException(ex, $"Error on {nameof(SaveChanges)} trying {nameof(SaveChanges)}"); return false; } } public virtual async Task SaveChangesAsync() { try { var result = await this.RepositoryContext.SaveChangesAsync().ConfigureAwait(false); return (result >= 0); } catch (Exception ex) { WriteLogException(ex, $"error on {nameof(SaveChangesAsync)} trying {nameof(SaveChangesAsync)}"); return false; } } public virtual bool Update(T entity) { try { this.RepositoryContext.Set().Update(entity); return true; } catch (Exception ex) { WriteLogException(ex, entity?.EntityInfo()); return false; } } public virtual async Task UpdateAsync(T entity, bool saveEntity = true) { try { this.RepositoryContext.Set().Update(entity); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, entity?.EntityInfo()); return false; } } public virtual async Task UpdateListAsync(List entities, bool saveEntity = true) { try { this.RepositoryContext.Set().UpdateRange(entities); if (saveEntity) return await this.SaveChangesAsync(); return true; } catch (Exception ex) { WriteLogException(ex, typeof(T).Name); return false; } } public void WriteLogDebug(string message, String entityMessage = null) { _logger.LogDebug(message, entityMessage); } public void WriteLogError(string message, string entityMessage = null) { _logger.LogError(message, "{entityMessage}", entityMessage); } public void WriteLogException(Exception exception, string entityMessage = null) { _logger.LogError(exception, "{entityMessage}", entityMessage); if (WebApiConfig.RaiseRepositoryExceptions) { throw exception; } } } }