using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Entity.Infrastructure; using System.Data.Entity.Validation; using System.Linq; using System.Linq.Dynamic.Core; using System.Threading.Tasks; using System.Web.Mvc; using Abp.Application.Services; using Abp.Application.Services.Dto; using Abp.Auditing; using Abp.Authorization; using Abp.Domain.Entities; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Extensions; using Abp.Linq; using Abp.Linq.Extensions; using Abp.Runtime.Caching; using Abp.UI; using IwbZero.IdentityFramework; using IwbZero.Runtime.Session; using IwbZero.ToolCommon; using IwbZero.ToolCommon.Lambda; using IwbZero.ToolCommon.LogHelpers; using Microsoft.AspNet.Identity; namespace IwbZero.AppServiceBase { public abstract class IwbZeroAsyncCrudAppService : ApplicationService, IIwbZeroAsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto where TUpdateInput : IEntityDto where TGetInput : IEntityDto where TDeleteInput : IEntityDto { protected readonly IRepository Repository; protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) { KeyFiledName = keyFiledName; AsyncQueryableExecuter = NullAsyncQueryableExecuter.Instance; LocalizationSourceName = IwbZeroConsts.LocalizationSourceName; Repository = repository; AbpSession = NullIwbSession.Instance; } #region 字段、属性 public new IIwbSession AbpSession { get; set; } public ICacheManager CacheManager { get; set; } public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } /// /// 自定义唯一字段名称(主键) /// protected string KeyFiledName { get; set; } /// /// 是否自动生成自定义字段(GUID) /// protected virtual bool KeyIsAuto { get; set; } = true; /// /// 自定义唯一字段存在提示信息 /// protected virtual string KeyExistMessage { get; set; } protected virtual string ExistMessage => string.IsNullOrEmpty(KeyExistMessage) ? L("KeyExistMessage") : KeyExistMessage; /// /// 自定义唯一字段不存在提示信息 /// protected virtual string KeyNotExistMessage { get; set; } protected virtual string NotExistMessage => string.IsNullOrEmpty(KeyNotExistMessage) ? L("KeyNotExistMessage") : KeyNotExistMessage; protected virtual string GetPermissionName { get; set; } protected virtual string GetAllPermissionName { get; set; } protected virtual string CreatePermissionName { get; set; } protected virtual string UpdatePermissionName { get; set; } protected virtual string DeletePermissionName { get; set; } #endregion 字段、属性 #region SelectList /// /// 获取 Function 下拉框选项 /// /// [DisableAuditing] public virtual async Task> GetSelectList() { var list = await Repository.GetAllListAsync(); var sList = new List(); foreach (var l in list) { sList.Add(new SelectListItem() { Value = $"{l.Id}", Text = $"{l.Id}" }); } return sList; } /// /// 获取 Function 下拉框选项 /// /// [DisableAuditing] public virtual async Task GetSelectStr() { var list = await Repository.GetAllListAsync(); string options = ""; foreach (var l in list) { options += ""; } return options; } #endregion SelectList #region CURD #region Query #region GetEntity/Dto /// /// 查询实体Dto /// /// /// [DisableAuditing] public virtual async Task GetDto(TGetInput input) { var entity = await GetEntity(input); return MapToEntityDto(entity); } /// /// 查询实体Dto /// /// /// [DisableAuditing] public virtual async Task GetDtoById(TPrimaryKey id) { var entity = await GetEntityById(id); return MapToEntityDto(entity); } /// /// 查询实体Dto(需指明自定义字段) /// /// /// [DisableAuditing] public virtual async Task GetDtoByNo(string no) { var entity = await GetEntityByNo(no); return MapToEntityDto(entity); } /// /// 查询实体 /// /// /// [DisableAuditing] public virtual async Task GetEntity(TGetInput input) { var entity = await GetEntityById(input.Id); return entity; } /// /// 查询实体 /// /// /// [DisableAuditing] public virtual async Task GetEntityById(TPrimaryKey id) { var exp = LambdaHelper.CreatePrimaryKeyExp(id); if (exp == null) { CheckErrors(string.Format(L("NoEntity"), id)); } return await Repository.FirstOrDefaultAsync(exp); } /// /// 查询实体(需指明自定义字段) /// /// /// [DisableAuditing] public virtual async Task GetEntityByNo(string no) { //CheckGetPermission(); if (string.IsNullOrEmpty(KeyFiledName)) { ThrowError("NoKeyFieldName"); } //LambdaObject obj = new LambdaObject() //{ // FieldType = LambdaFieldType.S, // FieldName = KeyFiledName, // FieldValue = no, // ExpType = LambdaExpType.Equal //}; //var exp = obj.GetExp(); var exp = LambdaHelper.CreateFieldExp(KeyFiledName, no); return exp == null ? null : await Repository.FirstOrDefaultAsync(exp); } #endregion GetEntity/Dto /// /// 分页查询 /// /// /// [DisableAuditing] public virtual async Task> GetAll(TGetAllInput input) { CheckGetAllPermission(); var query = CreateFilteredQuery(input); var totalCount = await AsyncQueryableExecuter.CountAsync(query); query = ApplySorting(query, input); query = ApplyPaging(query, input); var entities = await AsyncQueryableExecuter.ToListAsync(query); return new PagedResultDto( totalCount, entities.Select(MapToEntityDto).ToList() ); } /// /// 排序 /// /// The query. /// The input. protected virtual IQueryable ApplySorting(IQueryable query, TGetAllInput input) { ////Try to sort query if available //var sortInput = input as ISortedResultRequest; //if (sortInput != null) //{ // if (!sortInput.Sorting.IsNullOrWhiteSpace()) // { // return query.OrderBy(sortInput.Sorting); // } //} ////IQueryable.Task requires sorting, so we should sort if Take will be used. //if (input is ILimitedResultRequest) //{ // return query.OrderBy("CreationTime DESC"); //} //No sorting return _ApplySorting(query, input); } /// /// 排序 /// /// The query. /// The input. protected IQueryable _ApplySorting(IQueryable query, TGetAllInput input) { //Try to sort query if available var sortInput = input as ISortedResultRequest; if (sortInput != null) { if (!sortInput.Sorting.IsNullOrWhiteSpace()) { return query.OrderBy(sortInput.Sorting); } } //IQueryable.Task requires sorting, so we should sort if Take will be used. if (input is ILimitedResultRequest) { return query.OrderBy("CreationTime DESC"); } //No sorting return query; } /// /// 分页 /// /// The query. /// The input. protected virtual IQueryable ApplyPaging(IQueryable query, TGetAllInput input) { ////Try to use paging if available //var pagedInput = input as IPagedResultRequest; //if (pagedInput != null) //{ // return query.PageBy(pagedInput); //} ////Try to limit query result if available //var limitedInput = input as ILimitedResultRequest; //if (limitedInput != null) //{ // return query.Take(limitedInput.MaxResultCount); //} return _ApplyPaging(query, input); } /// /// 分页 /// /// The query. /// The input. protected IQueryable _ApplyPaging(IQueryable query, TGetAllInput input) { //Try to use paging if available var pagedInput = input as IPagedResultRequest; if (pagedInput != null) { return query.PageBy(pagedInput); } //Try to limit query result if available var limitedInput = input as ILimitedResultRequest; if (limitedInput != null) { return query.Take(limitedInput.MaxResultCount); } //No paging return query; } /// /// 根据给定的创建 过滤查询. /// /// The input. protected virtual IQueryable CreateFilteredQuery(TGetAllInput input) { var query = ApplyFilter(input); return query; } /// /// 过滤查询条件 /// protected virtual IQueryable ApplyFilter(TGetAllInput input) { var query = Repository.GetAll(); return ApplyFilter(query, input); } /// /// 过滤查询条件 /// protected IQueryable ApplyFilter(IQueryable query, TGetAllInput input) { var pagedInput = input as IIwbPagedRequest; if (pagedInput == null) { return query; } if (!string.IsNullOrEmpty(pagedInput.KeyWords)) { object keyWords = pagedInput.KeyWords; LambdaObject obj = new LambdaObject() { FieldType = (LambdaFieldType)pagedInput.FieldType, FieldName = pagedInput.KeyField, FieldValue = keyWords, ExpType = (LambdaExpType)pagedInput.ExpType }; var exp = obj.GetExp(); query = exp != null ? query.Where(exp) : query; } if (pagedInput.SearchList != null && pagedInput.SearchList.Count > 0) { List objList = new List(); foreach (var o in pagedInput.SearchList) { if (string.IsNullOrEmpty(o.KeyWords)) continue; object keyWords = o.KeyWords; objList.Add(new LambdaObject { FieldType = (LambdaFieldType)o.FieldType, FieldName = o.KeyField, FieldValue = keyWords, ExpType = (LambdaExpType)o.ExpType }); } var exp = objList.GetExp(); query = exp != null ? query.Where(exp) : query; } return query; } #endregion Query /// /// 添加 /// /// /// public virtual async Task Create(TCreateInput input) { CheckCreatePermission(); await CreateEntity(input); } /// /// 添加 /// /// /// /// protected async Task CreateEntity(TCreateInput input, bool isCheck = true) { if (!KeyFiledName.IsNullOrEmpty()) { var fieldValue = input.GetFiledValue(KeyFiledName); if (KeyIsAuto && fieldValue.IsNullOrEmpty()) { input.SetFiledValue(KeyFiledName, Guid.NewGuid().ToString("N")); } else { if (isCheck) { var exp = LambdaHelper.CreateFieldExp(KeyFiledName, fieldValue); using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete)) { if (await Repository.FirstOrDefaultAsync(exp) != null) { CheckErrors(ExistMessage); } } } } } var entity = MapToEntity(input); await Repository.InsertAsync(entity); await CurrentUnitOfWork.SaveChangesAsync(); return MapToEntityDto(entity); } /// /// 修改 /// /// /// public virtual async Task Update(TUpdateInput input) { CheckUpdatePermission(); await UpdateEntity(input); } /// /// 修改 /// /// /// /// protected async Task UpdateEntity(TUpdateInput input, TEntity entity = null) { entity = entity ?? await GetEntityById(input.Id); if (entity == null) { CheckErrors(NotExistMessage); } MapToEntity(input, entity); await CurrentUnitOfWork.SaveChangesAsync(); return MapToEntityDto(entity); } /// /// 删除 /// /// /// public virtual Task Delete(TDeleteInput input) { CheckDeletePermission(); return DeleteEntity(input); } /// /// 删除 /// /// /// /// protected async Task DeleteEntity(TDeleteInput input, bool isCheckNull = true) { if (isCheckNull && !string.IsNullOrEmpty(KeyFiledName)) { LambdaObject obj = new LambdaObject() { FieldType = LambdaFieldType.S, FieldName = KeyFiledName, FieldValue = input.GetFiledValue(KeyFiledName), ExpType = LambdaExpType.Equal }; var exp = obj.GetExp(); if (exp != null && await Repository.FirstOrDefaultAsync(exp) == null) { CheckErrors(NotExistMessage); } } try { await Repository.DeleteAsync(input.Id); await CurrentUnitOfWork.SaveChangesAsync(); } catch (DbUpdateException de) { this.LogError(de); ThrowError("CanNotCascadeDeleteMessage"); } catch (Exception e) { this.LogError(e); CheckErrors(e.Message); } } #endregion CURD #region MAP protected virtual TEntityDto MapToEntityDto(TEntity entity) { return ObjectMapper.Map(entity); } protected virtual TEntity MapToEntity(TCreateInput createInput) { return ObjectMapper.Map(createInput); } protected virtual void MapToEntity(TUpdateInput updateInput, TEntity entity) { ObjectMapper.Map(updateInput, entity); } protected virtual TOut IwbMap(object obj) { return ObjectMapper.Map(obj); } protected virtual TOut IwbMap(TIn obj) { return ObjectMapper.Map(obj); } #endregion MAP #region CHECK protected virtual int CheckGuid(int? guid) { if (guid == null || guid == 0) { ThrowError("GetGuidNoError"); return 0; } return (int)guid; } protected virtual void CheckErrors(string error) { throw new UserFriendlyException(error); } protected virtual void CheckErrors(IdentityResult identityResult) { identityResult.CheckErrors(LocalizationManager); } /// /// 抛出错误 /// /// /// 是否要本地化 protected virtual void ThrowError(string err, bool isLocalization = true) { CheckErrors(isLocalization ? L(err) : err); } protected virtual void CheckPermission(string permissionName) { if (!string.IsNullOrEmpty(permissionName)) { PermissionChecker.Authorize(permissionName); } } protected virtual void CheckGetPermission() { CheckPermission(GetPermissionName); } protected virtual void CheckGetAllPermission() { CheckPermission(GetAllPermissionName); } protected virtual void CheckCreatePermission() { CheckPermission(CreatePermissionName); } protected virtual void CheckUpdatePermission() { CheckPermission(UpdatePermissionName); } protected virtual void CheckDeletePermission() { CheckPermission(DeletePermissionName); } #endregion CHECK } #region AppServiceBase public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService where TGetAllInput : IPagedAndSortedResultRequest where TEntity : class, IEntity where TEntityDto : IEntityDto where TCreateInput : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService> where TEntity : class, IEntity where TEntityDto : IEntityDto where TUpdateInput : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } public abstract class IwbZeroAsyncCrudAppService : IwbZeroAsyncCrudAppService> where TEntity : class, IEntity where TEntityDto : IEntityDto where TUpdateInput : IEntityDto where TGetInput : IEntityDto { protected IwbZeroAsyncCrudAppService(IRepository repository, string keyFiledName = null) : base(repository) { KeyFiledName = keyFiledName; } } #endregion AppServiceBase }