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