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);
}
}
}