public class BaseRepository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class, IEntity
{
    private DatabaseContext _databaseContext;
    public BaseRepository(IDatabaseFactory databaseFactory)
    {
        Check.Argument.IsNotNull(databaseFactory, "databaseFactory");
        DatabaseFactory = databaseFactory;
    }
    protected IDatabaseFactory DatabaseFactory
    {
        get;
        private set;
    }
    protected DatabaseContext DatabaseContext
    {
        get
        {
            return _databaseContext ?? (_databaseContext = DatabaseFactory.Get());
        }
    }
    public void Dispose()
    {
        if (DatabaseContext != null)
            GC.SuppressFinalize(DatabaseContext);
        if (DatabaseFactory != null)
            GC.SuppressFinalize(DatabaseFactory);
    }
    public IEnumerable<TEntity> GetBySpec(ISpecification<TEntity> specification)
    {
        Check.Argument.IsNotNull(specification, "specification");
        IEnumerable<TEntity> result = DatabaseContext.CreateQuery<TEntity>().Where(specification.SatisfiedBy());
        return result;
    }
    public virtual void Add(TEntity entity)
    {
        Check.Argument.IsNotNull(entity, "entity");
        DatabaseContext.Save<TEntity>(entity);
    }
    public virtual void Delete(Guid id)
    {
        Check.Argument.IsNotNull(id, "id");
        TEntity entity = GetById(id);
        if (entity != null)
            DatabaseContext.Delete<TEntity>(entity);
    }
    public virtual void Delete(TEntity entity)
    {
        Check.Argument.IsNotNull(entity, "entity");
        DatabaseContext.Delete<TEntity>(entity);
    }
    public virtual TEntity GetById(Guid id)
    {
        return DatabaseContext.CreateQuery<TEntity>().SingleOrDefault<TEntity>(x => x.Id == id);
    }
    public virtual IEnumerable<TEntity> All()
    {
        return DatabaseContext.CreateQuery<TEntity>();
    }
    public IEnumerable<TEntity> GetPagedElements<S>(int pageIndex, int pageSize, Expression<Func<TEntity, S>> orderExpression, bool ascending)
    {
        Check.Argument.IsNotNegativeOrZero(pageIndex, "pageIndex");
        Check.Argument.IsNotNegative(pageSize, "pageSize");
        Check.Argument.IsNotNull(orderExpression, "orderExpression");
        IQueryable<TEntity> objectQuery = DatabaseContext.CreateQuery<TEntity>();
        return (ascending) ? objectQuery.OrderBy(orderExpression)
                                        .Skip((pageIndex - 1) * pageSize)
                                        .Take(pageSize)
                                        .ToList()
                            : objectQuery.OrderByDescending(orderExpression)
                                        .Skip((pageIndex - 1) * pageSize)
                                        .Take(pageSize)
                                        .ToList();
    }
    public IEnumerable<TEntity> GetPagedElements<S>(int pageIndex, int pageSize, Expression<Func<TEntity, S>> orderExpression, ISpecification<TEntity> specification, bool ascending)
    {
        Check.Argument.IsNotNegativeOrZero(pageIndex, "pageIndex");
        Check.Argument.IsNotNegative(pageSize, "pageSize");
        Check.Argument.IsNotNull(orderExpression, "orderExpression");
        Check.Argument.IsNotNull(specification, "specification");
        IQueryable<TEntity> objectQuery = DatabaseContext.CreateQuery<TEntity>();
        return (ascending) ? objectQuery.Where(specification.SatisfiedBy())
                                        .OrderBy(orderExpression)
                                        .Skip((pageIndex - 1) * pageSize)
                                        .Take(pageSize)
                                        .ToList()
                            : objectQuery.Where(specification.SatisfiedBy())
                                        .OrderByDescending(orderExpression)
                                        .Skip((pageIndex - 1) * pageSize)
                                        .Take(pageSize)
                                        .ToList();
    }
}
Jak widac wiekszosc metod tutaj to proste operacje na bazie danych za pomoca LINQ.Oprocz tego jest metoda ktora za pomoca wczesniej wspomnianej specyfikacji wyciaga dane z bazy. Teraz przyklad prostego repozytorium uzytkownika:
public class UserRepository : BaseRepository<User>, IUserRepository
{
    public UserRepository(IDatabaseFactory dbFactory)
        : base(dbFactory)
    {
    }
    public int CountAllUsers()
    {
        return DatabaseContext.Users.Count();
    }
    public int CountNumberOfOnlineUsers()
    {
        UserOnlineUsersSpecification specification = new UserOnlineUsersSpecification();
        return this.GetBySpec(specification).Count<User>();
    }
    public IEnumerable<User> GetAllUsersOnline()
    {
        UserOnlineUsersSpecification specification = new UserOnlineUsersSpecification();
        return this.GetBySpec(specification);
    }
    public User FindUserByUsername(string username)
    {
        Check.Argument.IsNotEmpty(username, "username");
        UserUsernameSpecification specification = new UserUsernameSpecification(username);
        return this.GetBySpec(specification).SingleOrDefault<User>();
    }
    public User FindUserByEmail(string email)
    {
        Check.Argument.IsNotEmpty(email, "email");
        Check.Argument.IsNotInvalidEmail(email, "email");
        UserEmailSpecification specification = new UserEmailSpecification(email);
        return this.GetBySpec(specification).SingleOrDefault<User>();
    }
}
W tym przykładzie możemy zobaczyć wykorzystanie już tych tajemniczych specyfikacji. Jak widać to rozwiązanie dosyć fajnie się prezentuje i oddziela logikę od samej bazy danych. W dodatku można ich wielokrotnie używać w rożnych miejscach naszego repozytorium. Dodałem 3 rodzaje specyfikacji do projektu związane z użytkownikiem. Wiec można sobie tez oglądnąć. To repozytorium ich właśnie używa.W zasadzie cały interfejs dostępu do bazy danych już jest prawie gotowy. Możliwe są ewentualnie małe poprawki. W projekcie testów NHibernate dodałem testy związane z klasami powyżej.

 
Brak komentarzy:
Prześlij komentarz