619 lines
19 KiB
C#

using HRD.AppLogger;
using HRD.WebApi.DAL;
using HRD.WebApi.Helpers;
using Microsoft.EntityFrameworkCore;
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<T> : IBaseRepository<T> where T : BaseEntityCore
{
private readonly ILoggerManager _logger;
protected DbContext RepositoryContext { get; private set; }
protected BaseRepositoryCore(WebApiBaseContext repositoryContext)
{
RepositoryContext = repositoryContext;
AppLoggerConfig.Init(
WebApiConfig.AssemblyName,
WebApiConfig.AssemblyVersion,
WebApiConfig.NlogDBLogLevel,
WebApiConfig.NlogFileLogLevel,
WebApiConfig.NlogLogDirectory);
_logger = new LoggerManager();
}
public virtual bool Add(T entity, bool saveEntity = true)
{
try
{
this.RepositoryContext.Set<T>().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<bool> AddAsync(T entity, bool saveEntity = true)
{
try
{
await this.RepositoryContext.Set<T>().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<bool> AddListAsync(List<T> list, bool saveEntity = true)
{
try
{
await this.RepositoryContext.Set<T>().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<T>().Remove(entity);
return this.SaveChanges();
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return false;
}
}
public virtual async Task<bool> DeleteAsync(T entity, bool saveEntity = true)
{
try
{
this.RepositoryContext.Set<T>().Remove(entity);
if (saveEntity)
return await this.SaveChangesAsync();
return true;
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return false;
}
}
public virtual async Task<bool> DeleteByIdAsync(int id, bool saveEntity = true)
{
try
{
var entity = await GetByIdAsync(id).ConfigureAwait(false);
this.RepositoryContext.Set<T>().Remove(entity);
if (saveEntity)
return await this.SaveChangesAsync();
return true;
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return false;
}
}
public virtual async Task<bool> 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<bool> 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<bool> 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<bool> 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<T> GetAll(bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return this.RepositoryContext.Set<T>().AsNoTracking().ToList();
}
else
{
return this.RepositoryContext.Set<T>().ToList();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual List<T> TakeList(int count, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return this.RepositoryContext.Set<T>().AsNoTracking().Take(count).ToList();
}
else
{
return this.RepositoryContext.Set<T>().Take(count).ToList();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public async Task<List<T>> TakePagesListAsync(int pageNumber, int pageSize, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await RepositoryContext
.Set<T>()
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.AsNoTracking()
.ToListAsync();
}
else
{
return await RepositoryContext
.Set<T>()
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual async Task<List<T>> TakeListAsync(int count, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>().AsNoTracking().Take(count).ToListAsync();
}
else
{
return await this.RepositoryContext.Set<T>().Take(count).ToListAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual async Task<List<T>> GetAllAsync(bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>().AsNoTracking().ToListAsync();
}
else
{
return await this.RepositoryContext.Set<T>().ToListAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual List<T> GetBy(Expression<Func<T, bool>> expression, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return this.RepositoryContext.Set<T>().Where(expression).AsNoTracking().ToList(); ;
}
else
{
return this.RepositoryContext.Set<T>().Where(expression).ToList(); ;
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual async Task<T> GetByAsync(Expression<Func<T, bool>> expression, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>().Where(expression).AsNoTracking().FirstOrDefaultAsync();
}
else
{
return await this.RepositoryContext.Set<T>().Where(expression).FirstOrDefaultAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual async Task<T> GetByIdAsync(int entityId, bool asNoTracking = false)
{
try
{
/* if (entityId == default) {
var items = await this.RepositoryContext.Set<T>().Take(1).ToListAsync();
entityId = items[0].GetEntityId();
}
*/
var entity = await this.RepositoryContext.Set<T>().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<T> GetBySqlAsync(string sql, bool asNoTracking = true)
{
// return await this.RepositoryContext.Set<T>().FromSqlInterpolated($"{apiFilter.ToString()}").AsNoTracking().ToListAsync();
try
{
return await this.RepositoryContext.Set<T>().FromSqlInterpolated($"{sql}").AsNoTracking().FirstOrDefaultAsync();
}
catch (Exception ex)
{
WriteLogException(ex, $"sql: {sql}");
return default;
}
}
public virtual async Task<T> GetByWithIncludeAsync(Expression<Func<T, bool>> expression, string navigationPropertyPath, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>()
.Where(expression)
.Include(navigationPropertyPath)
.AsNoTracking()
.FirstOrDefaultAsync();
}
else
{
return await this.RepositoryContext.Set<T>()
.Where(expression)
.Include(navigationPropertyPath)
.FirstOrDefaultAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
return default;
}
}
public virtual async Task<List<T>> GetListByAsync(Expression<Func<T, bool>> expression, bool asNoTracking = true)
{
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>().AsNoTracking().Where(expression).ToListAsync();
}
else
{
return await this.RepositoryContext.Set<T>().Where(expression).ToListAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
}
return default;
}
public virtual async Task<List<T>> TakeListByAsync(int count, Expression<Func<T, bool>> expression, bool asNoTracking = true)
{
if (count == 0) return await GetListByAsync(expression, asNoTracking);
var list = new List<T>();
try
{
if (asNoTracking)
{
return await this.RepositoryContext.Set<T>().AsNoTracking().Where(expression).Take(count).ToListAsync();
}
else
{
return await this.RepositoryContext.Set<T>().Where(expression).Take(count).ToListAsync();
}
}
catch (Exception ex)
{
WriteLogException(ex, typeof(T).Name);
}
return list;
}
public virtual async Task<List<T>> 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<T>().FromSqlInterpolated($"{sql}").AsNoTracking().ToListAsync();
}
catch (Exception ex)
{
WriteLogException(ex, $"sql:{sql}");
return default;
}
}
public virtual async Task<List<T>> GetListByConditionFromSqlRawAsync(string sql)
{
try
{
return await this.RepositoryContext.Set<T>().FromSqlRaw(sql).AsNoTracking().ToListAsync();
}
catch (Exception ex)
{
WriteLogException(ex, $"sql:{sql}");
return default;
}
}
public string GetTableName()
{
return AttributeReader.GetTableName<T>(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<bool> 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<T>().Update(entity);
return true;
}
catch (Exception ex)
{
WriteLogException(ex, entity?.EntityInfo());
return false;
}
}
public virtual async Task<bool> UpdateAsync(T entity, bool saveEntity = true)
{
try
{
this.RepositoryContext.Set<T>().Update(entity);
if (saveEntity)
return await this.SaveChangesAsync();
return true;
}
catch (Exception ex)
{
WriteLogException(ex, entity?.EntityInfo());
return false;
}
}
public virtual async Task<bool> UpdateListAsync(List<T> entities, bool saveEntity = true)
{
try
{
this.RepositoryContext.Set<T>().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);
}
public void WriteLogException(Exception exception, String entityMessage = null)
{
_logger.LogException(exception, entityMessage);
if (WebApiConfig.RaiseRepositoryExceptions)
{
throw exception;
}
}
public void WriteLogInfo(string message)
{
_logger.LogInfo(message);
}
public void WriteLogWarn(string message, String entityMessage = null)
{
_logger.LogWarn(message, entityMessage);
}
}
}