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