using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Abp.Dependency; using Abp.Domain.Entities; using Abp.Domain.Uow; using Abp.MultiTenancy; using Abp.Reflection.Extensions; namespace Abp.Domain.Repositories { /// /// Base class to implement . /// It implements some methods in most simple way. /// /// Type of the Entity for this repository /// Primary key of the entity public abstract class AbpRepositoryBase : IRepository, IUnitOfWorkManagerAccessor where TEntity : class, IEntity { /// /// The multi tenancy side /// public static MultiTenancySides? MultiTenancySide { get; private set; } public IUnitOfWorkManager UnitOfWorkManager { get; set; } public IIocResolver IocResolver { get; set; } static AbpRepositoryBase() { var attr = typeof (TEntity).GetSingleAttributeOfTypeOrBaseTypesOrNull(); if (attr != null) { MultiTenancySide = attr.Side; } } public abstract IQueryable GetAll(); public virtual IQueryable GetAllIncluding(params Expression>[] propertySelectors) { return GetAll(); } public virtual List GetAllList() { return GetAll().ToList(); } public virtual Task> GetAllListAsync() { return Task.FromResult(GetAllList()); } public virtual List GetAllList(Expression> predicate) { return GetAll().Where(predicate).ToList(); } public virtual Task> GetAllListAsync(Expression> predicate) { return Task.FromResult(GetAllList(predicate)); } public virtual T Query(Func, T> queryMethod) { return queryMethod(GetAll()); } public virtual TEntity Get(TPrimaryKey id) { var entity = FirstOrDefault(id); if (entity == null) { throw new EntityNotFoundException(typeof(TEntity), id); } return entity; } public virtual async Task GetAsync(TPrimaryKey id) { var entity = await FirstOrDefaultAsync(id); if (entity == null) { throw new EntityNotFoundException(typeof(TEntity), id); } return entity; } public virtual TEntity Single(Expression> predicate) { return GetAll().Single(predicate); } public virtual Task SingleAsync(Expression> predicate) { return Task.FromResult(Single(predicate)); } public virtual TEntity FirstOrDefault(TPrimaryKey id) { return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); } public virtual Task FirstOrDefaultAsync(TPrimaryKey id) { return Task.FromResult(FirstOrDefault(id)); } public virtual TEntity FirstOrDefault(Expression> predicate) { return GetAll().FirstOrDefault(predicate); } public virtual Task FirstOrDefaultAsync(Expression> predicate) { return Task.FromResult(FirstOrDefault(predicate)); } public virtual TEntity Load(TPrimaryKey id) { return Get(id); } public abstract TEntity Insert(TEntity entity); public virtual Task InsertAsync(TEntity entity) { return Task.FromResult(Insert(entity)); } public virtual TPrimaryKey InsertAndGetId(TEntity entity) { return Insert(entity).Id; } public virtual Task InsertAndGetIdAsync(TEntity entity) { return Task.FromResult(InsertAndGetId(entity)); } public virtual TEntity InsertOrUpdate(TEntity entity) { return entity.IsTransient() ? Insert(entity) : Update(entity); } public virtual async Task InsertOrUpdateAsync(TEntity entity) { return entity.IsTransient() ? await InsertAsync(entity) : await UpdateAsync(entity); } public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity) { return InsertOrUpdate(entity).Id; } public virtual Task InsertOrUpdateAndGetIdAsync(TEntity entity) { return Task.FromResult(InsertOrUpdateAndGetId(entity)); } public abstract TEntity Update(TEntity entity); public virtual Task UpdateAsync(TEntity entity) { return Task.FromResult(Update(entity)); } public virtual TEntity Update(TPrimaryKey id, Action updateAction) { var entity = Get(id); updateAction(entity); return entity; } public virtual async Task UpdateAsync(TPrimaryKey id, Func updateAction) { var entity = await GetAsync(id); await updateAction(entity); return entity; } public abstract void Delete(TEntity entity); public virtual Task DeleteAsync(TEntity entity) { Delete(entity); return Task.FromResult(0); } public abstract void Delete(TPrimaryKey id); public virtual Task DeleteAsync(TPrimaryKey id) { Delete(id); return Task.FromResult(0); } public virtual void Delete(Expression> predicate) { foreach (var entity in GetAll().Where(predicate).ToList()) { Delete(entity); } } public virtual Task DeleteAsync(Expression> predicate) { Delete(predicate); return Task.FromResult(0); } public virtual int Count() { return GetAll().Count(); } public virtual Task CountAsync() { return Task.FromResult(Count()); } public virtual int Count(Expression> predicate) { return GetAll().Where(predicate).Count(); } public virtual Task CountAsync(Expression> predicate) { return Task.FromResult(Count(predicate)); } public virtual long LongCount() { return GetAll().LongCount(); } public virtual Task LongCountAsync() { return Task.FromResult(LongCount()); } public virtual long LongCount(Expression> predicate) { return GetAll().Where(predicate).LongCount(); } public virtual Task LongCountAsync(Expression> predicate) { return Task.FromResult(LongCount(predicate)); } protected virtual Expression> CreateEqualityExpressionForId(TPrimaryKey id) { var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaBody = Expression.Equal( Expression.PropertyOrField(lambdaParam, "Id"), Expression.Constant(id, typeof(TPrimaryKey)) ); return Expression.Lambda>(lambdaBody, lambdaParam); } } }