Commit c9b20d97 authored by 阿星Plus's avatar 阿星Plus

Plus RepositoryBase

parent 04e69807
using System;
using System.Runtime.Serialization;
namespace Plus.Domain.Entities
{
[Serializable]
public class EntityNotFoundException : PlusException
{
public Type EntityType { get; set; }
public object Id { get; set; }
public EntityNotFoundException()
{
}
public EntityNotFoundException(SerializationInfo serializationInfo, StreamingContext context)
: base(serializationInfo, context)
{
}
public EntityNotFoundException(Type entityType, object id)
: this(entityType, id, null)
{
}
public EntityNotFoundException(Type entityType, object id, Exception innerException)
: base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException)
{
EntityType = entityType;
Id = id;
}
public EntityNotFoundException(string message)
: base(message)
{
}
public EntityNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}
\ No newline at end of file
namespace Plus.Domain.Entities
{
public interface IEntity
{
}
}
\ No newline at end of file
namespace Plus.Domain.Entities
{
/// <summary>
/// Defines interface for base entity type. All entities in the system must implement this interface.
/// </summary>
/// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam>
public interface IEntity<TPrimaryKey>
{
/// <summary>
/// Unique identifier for this entity.
/// </summary>
TPrimaryKey Id { get; set; }
/// <summary>
/// Checks if this entity is transient (not persisted to database and it has not an <see cref="Id"/>).
/// </summary>
/// <returns>True, if this entity is transient</returns>
bool IsTransient();
}
}
\ No newline at end of file
using System;
namespace Plus.Domain.Repositories
{
/// <summary>
/// 用于为实体定义自动存储库类型,可以用于 DbContext 类型
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class AutoRepositoryTypesAttribute : Attribute
{
public Type RepositoryInterface { get; }
public Type RepositoryInterfaceWithPrimaryKey { get; }
public Type RepositoryImplementation { get; }
public Type RepositoryImplementationWithPrimaryKey { get; }
public bool WithDefaultRepositoryInterfaces { get; set; }
public AutoRepositoryTypesAttribute(
Type repositoryInterface,
Type repositoryInterfaceWithPrimaryKey,
Type repositoryImplementation,
Type repositoryImplementationWithPrimaryKey)
{
RepositoryInterface = repositoryInterface;
RepositoryInterfaceWithPrimaryKey = repositoryInterfaceWithPrimaryKey;
RepositoryImplementation = repositoryImplementation;
RepositoryImplementationWithPrimaryKey = repositoryImplementationWithPrimaryKey;
}
}
}
\ No newline at end of file
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
namespace Plus.Domain.Repositories namespace Plus.Domain.Repositories
{ {
/// <summary>
/// IRepository
/// </summary>
public interface IRepository : ITransientDependency public interface IRepository : ITransientDependency
{ {
......
using Plus.Domain.Entities;
namespace Plus.Domain.Repositories
{
/// <summary>
/// <see cref="IRepository{TEntity,TPrimaryKey}"/>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public interface IRepository<TEntity> : IRepository<TEntity, int> where TEntity : class, IEntity<int>
{
}
}
\ No newline at end of file
using Plus.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
namespace Plus.Domain.Repositories
{
public interface ISupportsExplicitLoading<TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{
Task EnsureCollectionLoadedAsync<TProperty>(TEntity entity, Expression<Func<TEntity, IEnumerable<TProperty>>> collectionExpression, CancellationToken cancellationToken) where TProperty : class;
Task EnsurePropertyLoadedAsync<TProperty>(TEntity entity, Expression<Func<TEntity, TProperty>> propertyExpression, CancellationToken cancellationToken) where TProperty : class;
}
}
\ No newline at end of file
using Plus.Dependency;
using Plus.Domain.Entities;
using Plus.Domain.Uow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Plus.Domain.Repositories
{
/// <summary>
/// <see cref="IRepository{TEntity,TPrimaryKey}"/> 实现
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TPrimaryKey"></typeparam>
public abstract class PlusRepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>, IRepository, ITransientDependency where TEntity : class, IEntity<TPrimaryKey>
{
public IUnitOfWorkManager UnitOfWorkManager { get; set; }
public IIocResolver IocResolver { get; set; }
public abstract IQueryable<TEntity> GetAll();
public virtual IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors)
{
return GetAll();
}
public virtual List<TEntity> GetAllList()
{
return GetAll().ToList();
}
public virtual Task<List<TEntity>> GetAllListAsync()
{
return Task.FromResult(GetAllList());
}
public virtual List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).ToList();
}
public virtual Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate)
{
return Task.FromResult(GetAllList(predicate));
}
public virtual T Query<T>(Func<IQueryable<TEntity>, T> queryMethod)
{
return queryMethod(GetAll());
}
public virtual TEntity Get(TPrimaryKey id)
{
TEntity val = FirstOrDefault(id);
if (val == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return val;
}
public virtual async Task<TEntity> GetAsync(TPrimaryKey id)
{
TEntity entity = await FirstOrDefaultAsync(id);
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity;
}
public virtual TEntity Single(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Single(predicate);
}
public virtual Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate)
{
return Task.FromResult(Single(predicate));
}
public virtual TEntity FirstOrDefault(TPrimaryKey id)
{
return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id));
}
public virtual Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id)
{
return Task.FromResult(FirstOrDefault(id));
}
public virtual TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().FirstOrDefault(predicate);
}
public virtual Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
{
return Task.FromResult(FirstOrDefault(predicate));
}
public virtual TEntity Load(TPrimaryKey id)
{
return Get(id);
}
public abstract TEntity Insert(TEntity entity);
public virtual Task<TEntity> InsertAsync(TEntity entity)
{
return Task.FromResult(Insert(entity));
}
public virtual TPrimaryKey InsertAndGetId(TEntity entity)
{
return Insert(entity).Id;
}
public virtual Task<TPrimaryKey> 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<TEntity> InsertOrUpdateAsync(TEntity entity)
{
return (!entity.IsTransient()) ? (await UpdateAsync(entity)) : (await InsertAsync(entity));
}
public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity)
{
return InsertOrUpdate(entity).Id;
}
public virtual Task<TPrimaryKey> InsertOrUpdateAndGetIdAsync(TEntity entity)
{
return Task.FromResult(InsertOrUpdateAndGetId(entity));
}
public abstract TEntity Update(TEntity entity);
public virtual Task<TEntity> UpdateAsync(TEntity entity)
{
return Task.FromResult(Update(entity));
}
public virtual TEntity Update(TPrimaryKey id, Action<TEntity> updateAction)
{
TEntity val = Get(id);
updateAction(val);
return val;
}
public virtual async Task<TEntity> UpdateAsync(TPrimaryKey id, Func<TEntity, Task> updateAction)
{
TEntity 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<Func<TEntity, bool>> predicate)
{
foreach (TEntity item in GetAll().Where(predicate).ToList())
{
Delete(item);
}
}
public virtual Task DeleteAsync(Expression<Func<TEntity, bool>> predicate)
{
Delete(predicate);
return Task.FromResult(0);
}
public virtual int Count()
{
return GetAll().Count();
}
public virtual Task<int> CountAsync()
{
return Task.FromResult(Count());
}
public virtual int Count(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).Count();
}
public virtual Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
{
return Task.FromResult(Count(predicate));
}
public virtual long LongCount()
{
return GetAll().LongCount();
}
public virtual Task<long> LongCountAsync()
{
return Task.FromResult(LongCount());
}
public virtual long LongCount(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).LongCount();
}
public virtual Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate)
{
return Task.FromResult(LongCount(predicate));
}
protected static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId(TPrimaryKey id)
{
var lambdaParam = Expression.Parameter(typeof(TEntity));
var leftExpression = Expression.PropertyOrField(lambdaParam, "Id");
Expression<Func<object>> closure = () => id;
var rightExpression = Expression.Convert(closure.Body, leftExpression.Type);
var lambdaBody = Expression.Equal(leftExpression, rightExpression);
return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);
}
}
}
\ No newline at end of file
namespace Plus.Domain.Repositories
{
internal class UnitOfWorkExtensionDataTypes
{
public static string HardDelete { get; } = "HardDelete";
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment