piątek, 6 września 2013

[C#|Visual Studio] ServiceStack: IoC i ORM

Domyślnym kontenerem IoC w ServiceStacku jest Funq. Jest to prosty kontener zoptymalizowany pod kątem szybkości i lekkości. Domyślnie rejestrując w nim zależności rejestrujemy je jako Singletony. ServiceStack automatycznie wykona wstrzyknięcie zależności do publicznego property w klasach dziedziczących po Service. Przykład konfiguracji Funq (w pliku Global.asax i metodzie Configure).

public override void Configure(Funq.Container container)
{
    container.RegisterAutoWired<CounterService>();
    container.RegisterAutoWiredAs<CounterService, ICounterService>().ReusedWithin(ReuseScope.None);
    container.Register<ICounterService>(new CounterService());

    var cs = container.Resolve<ICounterService>();

    Console.WriteLine("Registered type is {0}", cs.GetType());
}

Zależności możemy rejestrować w trybie AutoWired, gdzie przeważnie wykonuje się mapowanie klasa na interfejs lub klasa w samą siebie. Do ręcznego ustawiania zależności wykorzystuje się z kolei metodę Register, natomiast do pobierania metodę Resolve. Jeżeli chcemy, by za każdym razem kontener zwracał nowy obiekt, musimy dopisać instrukcję ReusedWithin z parametrem None.

Mechanizmem do mapowania obiektowo - relacyjnego jest w ServiceStacku OrmLite. Jest to mapper prosty w użyciu i lekki, a zarazem bardzo wydajny, Kolejną jego zaletą jest multiplatformowość - działa z wieloma systemami, co widać przy próbie instalacji NuGetem.


Do tworzenia tabel wykorzystuje się obiekty POCO, które mogą być tymi samymi obiektami co DTO. Mamy do dyspozycji także znane z EntityFramework DataAnnotations. Przykład obiektu POCO:


[Route("/entry")]
[Authenticate]
[RequiredRole("User")]
public class Entry : IReturn<EntryResponse>
{
    [AutoIncrement]
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public int Count { get; set; }
}

OrmLite typy złożone serializuje i zapisuje jako BLOBy. Można natomiast zakładać constrainty poprzez użycie odpowiednich atrybutów. Do tworzenia połączeń służy typ IDbConnectionFactory, który można skonfigurować w kontenerze IoC.

public override void Configure(Funq.Container container)
{
    IDbConnectionFactory factory =
        new OrmLiteConnectionFactory(HttpContext.Current.Server.MapPath("~/App_Data/data.txt"),
                                     SqliteDialect.Provider);

    container.Register<IDbConnectionFactory>(factory);

    container.RegisterAutoWiredAs<CounterService, ICounterService>();
}

Operacje na bazie przeprowadza się w bardzo wygodny sposób

public class CounterService : ICounterService
{
    public IDbConnectionFactory DbConnectionFactory { get; set; }
    private int _counter;

    public void Add(int i)
    {
        _counter += i;
        using (var dbConn = DbConnectionFactory.CreateDbConnection())
        {
            dbConn.Open();
            dbConn.CreateTable<Entry>();
            dbConn.Insert<Entry>(new Entry()
                                     {
                                         Count = i,
                                         Date = DateTime.Now
                                     });
        }
    }

    public int Print()
    {
        using (var dbConn = DbConnectionFactory.CreateDbConnection())
        {
            //WHERE - lambda expression lub SQL jako string
            dbConn.Open();
            return dbConn.Select<Entry>().Sum(x => x.Count);
        }
    }
}

Brak komentarzy:

Prześlij komentarz