using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Transactions; using System; using Church.Net.DAL.EF; using System.Linq; using Church.Net.Utility; using System.Threading.Tasks; using Church.Net.Entity.Interface; using System.ComponentModel.DataAnnotations; using System.Reflection; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Church.Net.DAL.EFCoreDBF { public class CombinedKeyCrudDALCBase : ICombinedKeyCrudDAL where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new() { private readonly DatabaseOptions databaseOptions; public CombinedKeyCrudDALCBase(DatabaseOptions databaseOptions) { this.databaseOptions = databaseOptions; InitKeyProperty(); } public IQueryable GetDbSet() { //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); return databaseOptions.GetDbContext().Set().AsNoTracking(); //return result; } public ChurchNetContext GetDbContext() { //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); return databaseOptions.GetDbContext();//.Set().AsNoTracking(); //return result; } public virtual T First(Func filter = null) { using (var dbContext = GetDbContext()) { return dbContext.Set().Where(filter ?? (s => true)).FirstOrDefault(); } } public virtual T GetById(IEnumerable Ids) { return this.GetQuery(Ids).FirstOrDefault(); } //public virtual T GetByRefndx(string refndx) //{ // return MapDBModelToEntity(GetFirstDBModelByRefndx(refndx, this.actionScreen)); //} public virtual IEnumerable GetAll(Func filter = null) { //var dbObjs = GetDbSet().ToArray(); //IEnumerable list = GetDbSet().Where(filter ?? (s => true)).ToList(); return GetDbSet().AsNoTracking().Where(filter ?? (s => true)).ToList(); } public virtual int Create(T entity) { this.CheckCombinedKeyIsEmpty(entity); this.ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { dbContext.Add(entity); return dbContext.SaveChanges(); } } public virtual Task CreateAsync(T entity) { this.CheckCombinedKeyIsEmpty(entity); this.ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { dbContext.Add(entity); //CreateDone(entity, newDbObj); return dbContext.SaveChangesAsync(); } } public int CreateOrUpdate(T entity) { int result = 0; this.ConvertUTCTime(entity); if (CheckExist(entity)) { result = this.Update(entity); } else { result = this.Create(entity); } return result; } public virtual int Update(T entity) { //if (!this.CheckExist(entity)) //{ // throw new ArgumentNullException("the Id is not exist."); //} this.ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { dbContext.Update(entity); return dbContext.SaveChanges(); } } public virtual void CreateDone(T entity) { } public virtual void UpdateDone(T entity) { } public virtual int UpdateRange(IEnumerable entities) { using (var dbContext = GetDbContext()) { dbContext.UpdateRange(entities); return dbContext.SaveChanges(); } } public virtual int Delete(T obj) { using (var dbContext = GetDbContext()) { dbContext.Remove(obj); return dbContext.SaveChanges(); } } public virtual int Delete(IEnumerable combinedKeyIds) { var obj = this.GetById(combinedKeyIds); return obj == null ? this.Delete(obj) : 0; } public int Delete(Func filter) { var list = GetDbSet().Where(filter).ToList(); using (var dbContext = GetDbContext()) { foreach (var item in list) { dbContext.Remove(item); } return dbContext.SaveChanges(); } } public virtual bool CheckExist(T obj) { //var query = GetDbSet().AsQueryable(); var query = GetAll(); List props = new List(); for (int i = 0; i < keyProps.Count; i++) { var prop = keyProps[i]; props.Add(prop); var value = prop.GetValue(obj)?.ToString(); query = query.Where(e => prop.GetValue(e)?.ToString() == value).ToList(); } return query.Any(); } private void ConvertUTCTime(T entity) { var props = typeof(T).GetProperties(); foreach (var prop in props) { if (prop.PropertyType == typeof(DateTime)) { //do stuff like prop.SetValue(t, DateTime.Now, null); DateTime utcTime = ((DateTime)prop.GetValue(entity)).ToUniversalTime(); prop.SetValue(entity, utcTime, null); } } } private List keyProps; private void InitKeyProperty() { keyProps = typeof(T).GetProperties().Where( prop => Attribute.IsDefined(prop, typeof(KeyAttribute))).OrderBy(prop => prop.GetCustomAttribute().Order ) .ToList(); } private IQueryable GetQuery(IEnumerable Ids) { using (var dbContext = GetDbContext()) { var query = dbContext.Set().AsQueryable(); for (int i = 0; i < keyProps.Count; i++) { query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i)); } return query; } } private void CheckCombinedKeyIsEmpty(T entity) { for (int i = 0; i < keyProps.Count; i++) { if (string.IsNullOrEmpty(keyProps[i].GetValue(entity)?.ToString())) { throw new Exception($"Combined Key [{keyProps[i].Name}] not defined!"); } } } } }