sobota, 7 sierpnia 2010

Projektowanie interfejsu zwiazanego z baza danych.

Dzisiaj zajmiemy się projektowaniem podstawowych interfejsów związanych z logika biznesowa i baza danych. Miedzy innymi implementacja encji, interfejsu repozytorium.

Encje
Zacznijmy od tworzenia encji. Na potrzeby budowania architektury aplikacji narazie stworze tylko 1 encje. Będzie nią użytkownik. Zacznijmy od zaimplementowania interfejsu encji. Częścią wspólna każdej encji jest id. Więc nasz interfejs będzie posiadał właśnie to pole.
public interface IEntity
{
    Guid Id { get; set; }
}
Aby ułatwić sobie sprawę stworzymy bazowa encje która będzie implementowała powyższy interfejs. Spowoduje to ze nie będziemy musieć w każdej encji wypisywać pola id. W razie gdyby pojawiły się inne pola które będą wspólne równie łatwo będzie można modyfikowac bazowa encje co spowoduje zmiany w wszystkich encjach.
Oto implementacja bazowej encji:
public abstract class BaseEntity : IEntity
{
    public virtual Guid Id { get; set; }
}

Jak juz mamy podstawowe typy z których będą dziedziczyły nasze encje możemy teraz zaimplementować pierwsza z nich:
public class User : BaseEntity, IEntity
{        
    public virtual string Username { get; set; }

    public virtual string Password { get; set; }

    public virtual string Email { get; set; }

    public virtual string PasswordQuestion { get; set; }

    public virtual string PasswordAnswer { get; set; }

    public virtual bool isLockedOut { get; set; }

    public virtual DateTime LastActivityDate { get; set; }

    public virtual DateTime LastLoginDate { get; set; }

    public virtual DateTime LastLockedOutDate { get; set; }

    public virtual DateTime CreatedDate { get; set; }

}

Repozytoria
Następnie chciałbym co nieco powiedzieć na temat obiektów które będzie można znaleźć w moim projekcie. Są to repozytoria. Repozytorium jest to klasa która bezpośrednio ma dostęp do bazy danych. Udostępnia on podstawowe operacje CRUD jak i inne bezpośrednio związane z dana encja. Pośredniczy miedzy baza a usługami które te dane będą potrzebowały. Pozwala to na uniezależniane projektu od konkretnego ORM-a. Podmiana wymaga jedynie zaimplementowania kontekstu bazy danych oraz poszczególnych repozytoriów. Implementacja interfejsu repozytorium wygląda tak:
public interface IRepository<TEntity> where TEntity : class
{
    TEntity GetById(Guid id);
    IEnumerable<TEntity> GetBySpec(ISpecification<TEntity> spec);
    void Add(TEntity entity);
    void Delete(Guid id);
    void Delete(TEntity entity);
    IEnumerable<TEntity> GetPagedElements<S>(int pageIndex, int pageSize, Expression<Func<TEntity, S>> orderExpression, bool ascending);
    IEnumerable<TEntity> GetPagedElements<S>(int pageIndex, int pageSize, Expression<Func<TEntity, S>> orderExpression, ISpecification<TEntity> specification, bool ascending);
    IEnumerable<TEntity> All();
}
Większość funkcji tutaj jest raczej zrozumiała. Jedyna zagadka możne być ISpecifcation interfejs. Spójrzmy na przykładowa implementacje:
public class UserOnlineUsersSpecification : Specification<User>
{
    private DateTime _onlineTime;

    public UserOnlineUsersSpecification()
    {
           
    }

    public override Expression<Func<User, bool>> SatisfiedBy()
    {
        _onlineTime = DateTime.Now.AddMinutes(-5);

        return x => x.LastActivityDate >= _onlineTime;
    }
}
Ta specyfikacja ma za zadanie zwrócić wyrażenie lamba które pozwoli nam znaleźć aktualnie użytkowników online. Jak widzymy kazda specyfikacja sklada sie metody SatisfiedBy która zwraca wyrażenie lamba. To wyrażenie jest wykorzystywane w bazie do pobrania odpowiednich danych. Krótko mówiac jest to mała cześć logiki biznesowej opakowana w klase co powoduje że może byc używana w wielu miejscach i unikamy powtórzeń w kodzie. Wiecej na temat tego wzorca mozna znaleść na Wikipedi

W nastepnych wpisach zajmiemy sie juz konkretna implementacja klas zwiazanych z NHibernate i baza danych.

Brak komentarzy:

Prześlij komentarz