using CanDoo.Contracts; using CanDoo.Core.Data; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CanDoo.Data; using System.Linq.Expressions; using CanDoo.Extensions; using CanDoo.Core.Caching; using Mehdime.Entity; using System.Data.Entity; using System.Linq.Dynamic; using CanDoo.Core.Data.Extensions; using CanDoo.Filter; using CanDoo.Exceptions; using System.Diagnostics.Contracts; namespace CanDoo.Data.Entity.Services { public abstract class ServiceBase<TEntity> : ServiceBase<TEntity, Guid> where TEntity : class, IEntity<Guid>,IEntity, new() { } public abstract class ServiceBase<TEntity, TKey> : IServiceBase<TEntity, TKey> where TEntity : class, IEntity<TKey>, new() { #region 属性 public virtual IQueryable<TEntity> Entities { get { return Repository.Entities; } } public IRepository<TEntity, TKey> Repository { get; set; } /// <summary> /// 很快要删除此属性 /// </summary> private IUnitOfWork UnitOfWork { get { return Repository.UnitOfWork; } } #endregion public IDbContextScopeFactory DbScopeFactory { get; set; } public ServiceBase() { OnDeleting += BeforeDelete; OnDeleted += AfterDelete; OnUpdating += BeforeUpdate; OnUpdated += AfterUpdate; OnAdding += BeforeAdd; OnAdded += AfterAdd; OnQuerying += AfterBeforeQuery; OnQueried += AfterQuery; } /// <summary> /// 这个改成内部方法,,读出来总要在操作单元(事务中使用,不然读出来也无法惰性加载 /// </summary> /// <param name="Id"></param> /// <returns></returns> public TEntity GetById(TKey Id) { return Repository.GetByKey(Id); } /// <summary> /// 根据id读出只读实体,在action内,实体可以惰性加载 /// </summary> /// <param name="Id"></param> /// <param name="readOnlyAcion"></param> public void GetById(TKey Id, Action<TEntity> readOnlyAcion) { using (var scope = DbScopeFactory.CreateReadOnly()) { TEntity entity = GetById(Id); readOnlyAcion(entity); } } /// <summary> /// 根据id读出实体,在action内,实体可以惰性加载,如果查不数据,new一个对象出来 /// </summary> /// <param name="Id"></param> /// <param name="readOnlyLoadAction"></param> public void LoadById(TKey Id, Action<TEntity> readOnlyLoadAction) { using (var scope = DbScopeFactory.CreateReadOnly()) { TEntity entity = GetById(Id); if (entity == null) { entity = new TEntity(); entity.Id = Id; } readOnlyLoadAction(entity); } } #region GetPaged public PageResult<TResult> GetPaged<TResult>(Expression<Func<TEntity, TResult>> selector, System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, string sortExpression = "", int pagesize = 10, int pageindex = 0, string includeProperties = "") { using (var dbContextScope = DbScopeFactory.CreateReadOnly()) { var query = Entities; if (filter != null) { query = query.Where(filter); } if (!string.IsNullOrEmpty(includeProperties)) { foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } } if (!string.IsNullOrEmpty(sortExpression)) { query = query.SortBy(sortExpression); } else { query = query.SortBy("Id desc"); } var selectedQuery = query.Select(selector); selectedQuery = selectedQuery.Skip(pagesize * pageindex).Take(pagesize); var data = selectedQuery.ToArray(); //Entities.Where(filter).OrderBy(p => p.Id).Skip(pagesize * pageindex).Take(pagesize).ToArray(); return new PageResult<TResult> { Data = data, Total = this.Repository.Count(filter) }; } } public PageResult<TResult> GetPaged<TResult>(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Expression<Func<TEntity, TResult>> selector = null, Func<IQueryable<TResult>, IOrderedQueryable<TResult>> orderBy = null, int pagesize = 10, int pageindex = 0, string includeProperties = "") { //using (var dbContextScope = _dbContextScopeFactory.Create()) { IQueryable<TEntity> query = this.Entities; if (filter != null) { query = query.Where(filter); } foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } IQueryable<TResult> qResult = query.Select(selector); IOrderedQueryable<TResult> qSort; if (orderBy != null) { qSort = orderBy(qResult); qResult = qSort.Skip(pagesize * pageindex).Take(pagesize); } else { qResult = qResult.Skip(pagesize * pageindex).Take(pagesize); } return new PageResult<TResult> { Data = qResult.ToArray(), Total = query.Count() }; } } public IQueryable<TEntity> Get(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "") { //q.Skip(GridList.PageIndex * GridList.PageSize).Take(GridList.PageSize).ToList() IQueryable<TEntity> query = this.Entities; if (filter != null) { query = query.Where(filter); } foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } if (orderBy != null) { return orderBy(query); } else { return query; } } #endregion #region 增删改查 #region Add public OperationResult AddEntity(TEntity Entity) { Entity.CheckNotNull("Entity"); using (var dbContextScope = DbScopeFactory.Create()) { var result = OperationResult.NoChanged; if (OnAdding != null) { result = BeforeAdd(new[] { Entity.Id }, new[] { Entity }); if (result.ResultType != OperationResultType.NoChanged && result.ResultType != OperationResultType.Success) return result; } Repository.Insert(Entity);// try { result = dbContextScope.SaveChanges() > 0 ? OperationResult.Success : OperationResult.NoChanged; } catch (Exception ex) { result = new OperationResult(OperationResultType.Error, ex.Message); } //只有操作成功才执行AfterAdd事件 if (result.ResultType == OperationResultType.Success && OnAdded != null) { AfterAdd(new[] { Entity.Id }, new[] { Entity }); } return result; } } public OperationResult AddEntity(IEnumerable<TEntity> entities) { entities.CheckNotNull("entities"); using (var dbContextScope = DbScopeFactory.Create()) { Repository.Insert(entities); return dbContextScope.SaveChanges() > 0 ? new OperationResult(OperationResultType.Success, "数据添加成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult AddEntity(TKey id, Func<TEntity, OperationResult> addFunc) { using (var scope = DbScopeFactory.Create()) { var result = OperationResult.NoChanged; try { TEntity entity = new TEntity(); entity.Id = id; result = addFunc(entity); if (result.ResultType == OperationResultType.Success) { //执行添加事件 result = BeforeAdd?.Invoke(new[] { id }, new[] { entity }) ?? OperationResult.Success; if (result == null || result.ResultType == OperationResultType.Success) { Repository.Insert(entity); result = scope.SaveChanges() > 0 ? OperationResult.Success : OperationResult.NoChanged; } } if (result.ResultType == OperationResultType.Success) { AfterAdd?.Invoke(new[] { id }, new[] { entity }); } } catch (Exception ex) { result = new OperationResult(OperationResultType.Error, ex.Message, ex); } return result; } } #endregion #region Delete public OperationResult DeleteEntity(TEntity Entity) { Entity.CheckNotNull("Entity"); return Repository.Delete(Entity) > 0 ? new OperationResult(OperationResultType.Success, "数据删除成功!") : new OperationResult(OperationResultType.NoChanged); } public OperationResult DeleteEntity(TKey id) { using (var dbContextScope = DbScopeFactory.Create()) { return Repository.Delete(id) > 0 ? new OperationResult(OperationResultType.Success, "数据删除成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult DeleteEntity(IEnumerable<TEntity> Entities) { Entities.CheckNotNull("Entities"); using (var dbContextScope = DbScopeFactory.Create()) { return Repository.Delete(Entities) > 0 ? new OperationResult(OperationResultType.Success, "数据删除成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult DeleteEntity(List<TKey> ids) { ids.CheckNotNull("ids"); using (var dbContextScope = DbScopeFactory.Create()) { Repository.Delete(p => ids.Contains(p.Id)); return dbContextScope.SaveChanges() > 0 ? new OperationResult(OperationResultType.Success, "数据删除成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult DeleteEntity(Expression<Func<TEntity, bool>> predicate) { using (var dbContextScope = DbScopeFactory.Create()) { return Repository.Delete(predicate) > 0 ? new OperationResult(OperationResultType.Success, "数据删除成功!") : new OperationResult(OperationResultType.NoChanged); } } #endregion #region Update public OperationResult UpdateEntity(IEnumerable<TEntity> Entities) { Entities.CheckNotNull("Entities"); using (var dbContextScope = DbScopeFactory.Create()) { UnitOfWork.TransactionEnabled = true; foreach (var item in Entities) { Repository.Update(item); } return UnitOfWork.SaveChanges() > 0 ? new OperationResult(OperationResultType.Success, "数据更新成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult UpdateEntity(TEntity Entity) { Entity.CheckNotNull("Entity"); using (var dbContextScope = DbScopeFactory.Create()) { return Repository.Update(Entity) > 0 ? new OperationResult(OperationResultType.Success, "数据更新成功!") : new OperationResult(OperationResultType.NoChanged); } } public OperationResult UpdateEntity(TKey id, Func<TEntity, OperationResult> updateFunc) { using (var scope = DbScopeFactory.Create()) { var result = OperationResult.NoChanged; try { TEntity entity = GetById(id); if (entity == null) { return new OperationResult(OperationResultType.QueryNull, "你要更新的数据找不到,可能已经被删除。"); } result = updateFunc(entity); if (result.ResultType == OperationResultType.Success) { //执行更新前事件 result = BeforeUpdate?.Invoke(new[] { id }, new[] { entity }) ?? OperationResult.Success; ; if (result.ResultType == OperationResultType.Success) //Repository.Update(entity); 这个不需要了,对象已经在被跟踪状态 result = scope.SaveChanges() > 0 ? OperationResult.Success : OperationResult.NoChanged; } if (result.ResultType == OperationResultType.Success) { AfterUpdate?.Invoke(new[] { id }, new[] { entity }); } } catch (Exception ex) { result = new OperationResult(OperationResultType.Error,ex.Message,ex); } return result; } } #endregion #endregion #region AttachEntity public TEntity AttachEntity(TEntity entity) { return this.Repository.AttachEntity(entity); } public void AttachEntity(ICollection<TEntity> existItems, TKey[] newItemIDs) { throw new NotImplementedException(); } public TEntity AttachEntityByKey(TKey keyID) { TEntity entity = new TEntity(); entity.Id = keyID; return AttachEntity(entity); } /// <summary> /// 更新原集合中的元素 /// </summary> /// <typeparam name="TData"></typeparam> /// <typeparam name="TDataKey"></typeparam> /// <param name="orignEntities"></param> /// <param name="newEntities"></param> protected void ReplaceEntity<TData>(ICollection<TData> orignEntities, ICollection<TData> newEntities) { //删除旧的 orignEntities.Where(p => newEntities.Contains(p) == false).ToList().ForEach(deleted => orignEntities.Remove(deleted)); //添加新的 newEntities.Where(p => orignEntities.Contains(p) == false).ToList().ForEach(added => orignEntities.Add(added)); } #endregion #region Event public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnAdded; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnAdding; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnDeleted; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnDeleting; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnQueried; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnQuerying; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnUpdated; public event Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> OnUpdating; #endregion #region Event Handler 事件处理器 public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> AfterAdd; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> AfterBeforeQuery; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> AfterDelete; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> AfterQuery; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> AfterUpdate; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> BeforeAdd; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> BeforeDelete; public Func<IEnumerable<TKey>, IEnumerable<TEntity>, OperationResult> BeforeUpdate; #endregion #region 事务操作 public void KeepReading(Action readFromeDbOnlyAction) { using (var dbContextScope = DbScopeFactory.CreateReadOnly()) { readFromeDbOnlyAction(); } } public OperationResult Save(Func<OperationResult> saveAction) { using (var dbContextScope = DbScopeFactory.Create()) { OperationResult or = OperationResult.NoChanged; #region 执行保存过程 or = saveAction?.Invoke(); if (or.ResultType != OperationResultType.Success && or.ResultType != OperationResultType.NoChanged) { return or; } #endregion try { or = dbContextScope.SaveChanges() > 0 ? OperationResult.Success : OperationResult.NoChanged; } catch (CanDooException ex) { or = new OperationResult(OperationResultType.Error, ex.Message); } return or; } } #endregion } }