Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Persistence modelu pomocí ActiveRecord

15.16 - 21. ledna 2009 | ASP.NET 2.0

V architektuře naší MVC aplikace jsme se dostali již poměrně daleko. Vybrali jsme si šablonovací systém, máme vyřešenou integraci s IoC kontejnerem, vymazlené routování, připravené model bindery a teď je na čase nějakým způsobem model persistovat. Existuje mnoho způsobů, jak toho dosáhnout.

  1. Persistenci si můžete řešit sami na úrovni ADO.NET. Jenže proč řešit něco, co už někdo stokrát vyřešil?
  2. Použít nějaký ORM nástroj.

ORM nástrojů na výběr máme dnes tolik, že je stěží na prstech spočítáme, jaký si tedy vybrat? Pro mnohé bude první volbou LINQ to SQL. Pro jednoduché mapování (1:1) a tam, kde je možné být závislý pouze na MS SQL, je toto řešení dostačující. Osobně preferuju malinko složitější cestu, ale ve výsledku myslím, že mnohem mocnější. :)

Castle ActiveRecord a Repository pattern

Já ve svých posledních proktech používám Castle ActiveRecord, což je implemenatce návrhového vzoru ActiveRecord nad ORM frameworkem NHibernate. V mnoha ohledech práci s NHibernatem značně zjednodušuje, ať už je to mapování, automatickou správu session a podobně. Způsoby užití jsme už popsal ve spotu ActiveRecord vs. Repository pattern. Další výhodou je, že vše, co funguje v NHibernate (LINQ, Spatial, vlastní mapovací typy), můžete použí i s Castle ActiveRecord.

Datové třídy však nedědím z bázové třídy ActiveRecordBase, ale používám Repository, která se stará o CRUD operace s entitou. Pokud chcete mít mapování a závislost na ActiveRecord snadno odstranitelnou, můžete mapovací atributy vyčlenit třeba do samostatného partial souboru. Ale nejspíš nikdy v životním cyklu vaší aplikace nebudete ORM framework měnit, takže se trápit metadaty o databázovém schema je celkem zbytečné…

Základem pro repository je generické rozhraní IRepository<>, pro snadnou automatickou registraci repositoří v kontejneru ještě nadefinujeme ještě i negenerické rozhraní:

using Castle.ActiveRecord;

public interface IRepository {}

public interface IRepository<Tentity> : IRepository where TEntity : class {
  TEntity FindById(int id);
  void Save(TEntity entity);
  void Delete(TEntity entity);
}

public abstract class ActiveRecordRepositoryBase<TEntity>
  : IRepository<TEntity> where TEntity : class {
  public virtual TEntity FindById(int id) {
    return ActiveRecordMediator<TEntity>.FindByPrimaryKey(id);
  }
  public virtual void Save(TEntity entity) {
    ActiveRecordMediator<TEntity>.SaveAndFlush(entity);
  }
  public virtual void Delete(TEntity entity) {
    ActiveRecordMediator<TEntity>.DeleteAndFlush(entity);
  }
}

Pojďme si podporu pro ActiveRecord integrovat do naší MVC aplikace.

Integrace přes Binsor

Výhodou projektů z Castle, je, že se mezi sebou dokážou integrovat a využívat navzájem výhod své synergie. Nejprve si do projektu přidáme referenci na knihovnu Castle.ActiveRecord a ještě Castle.Facilities.ActiveRecordIntegration. Následně zaregistrujeme v souboru Windsor.boo facility pro integraci ActiveRecordu do IoC kontejneru:

import System.Reflection

// podpora ActiveRecord v kontejneru
facility ActiveRecordFacility:
  configuration:
    @isWeb = true, isDebug = false
    assemblies = [ Assembly.Load("MyApplication.Entities") ]
    config(keyvalues, item: add):
      show_sql = true
      command_timeout = 500
      dialect = 'NHibernate.Dialect.MsSql2005Dialect'
      connection.provider = 'NHibernate.Connection.DriverConnectionProvider'
      connection.driver_class = 'NHibernate.Driver.SqlClientDriver'
      connection.connection_string_name = 'CONN_DEMO'

Teď ještě potřebujeme ve web.configu přidat ConnectionString pod klíčem CONN_DEMO a volitelně přidat životnost session na jeden request. To uděláte tak, že do sekce system.web\httpModules přidáte následující modul:

<add
  name="PerRequestSessionScope"
  type="Castle.ActiveRecord.Framework.SessionScopeWebModule, Castle.ActiveRecord"/>

To má za výhodu to, že všechny vaše dotazy za jeden request se chovají jako jedna transakce. Takže integrace frameworku, je hotová. Teď ještě přidáme automatickou registraci samotných repositoří.

for repository in AllTypesBased of IRepository("MyApplication.Entities"):
  component repository.Name.ToLower(), repository.GetInterfaces()[0], repository:
    lifestyle PerWebRequest

Tímto se zaregistrují všechny repository, které dědí z ActiveRecordRepositoryBase a jsou pak ve vašich komponentách dostupné jako IRepository<User> (příklad pro entitu User). Pokud budete mít v repository více metod, je dobré vytvořit pro ně kontrakt, který obsahuje kontrakt generické repository. Například takto:

public interface IUsersRepository : IRepository<User> {
  User FindUserByEmail(string email);
}

Registrace takovýchto komponent už je o něco složitější, ale dá se to také zvládnout. Nejprve si zavedeme konvenci, že repository, které takovéto kontrakty implementují, se budou jmenovat až na I na začátku stejně. :) Takže pro kontrakt IUsersRepository budeme mít konkrétní implementaci UsersRepository atd. Pro jejich registraci využijeme metodu System.Type.FindInterfaces, která bere jako první argument delegát na vyhledávací funkci a druhý argument jsou hledací kritéria. Takže si vytvoříme funkci, která splňuje kontrakt delegáta, a následně ji hned využijeme pro registraci:

def contains_name(t as Type, o as Object):
  return t.Name.Contains(o.ToString())

for repository in AllTypesBased of IRepository("MyApplication.Entities"):
  repository_interface = repository.FindInterfaces(contains_name, repository.Name)
  component repository.Name.ToLower(), repository_interface, repository:
    lifestyle PerWebRequest

Cool ne? Pár řádků konfigurace a nejspíš máme vystaráno, tedy když dodržíme stanovenou konvenci, tak už se o registraci komponent datové vrstvy nemusíme starat. Stejně tak už máme zaregistrované model bindery a controllery. Trošku nám to konfigurace povyrostla, ale díky možnostem, které nám přináší Binsor, je to jen zlomek toho, co by bylo potřeba napsat v XML.

Projektík se nám pomalu rozrůstá, sice stále nic nedělá, ale je to dobrý základ pro pořádný web. Pokusím se ho hodit někam do SVN, aby bylo lehčí se v projektu orientovat a byly vidět jednotlivé změny.

K WebExpu ještě jednou a pořádně

16.19 - 25. října 2008 | Webdesign

Už je to týden, co nám skončila přednáška o ASP.NET 3.5 / futures na konferenci WebExpo 2008. Rád bych se k této konferenci ještě ohlédl.

Moje prezentace

Když mě začátkem léta oslovil Vašek Stoupa, jestli nechci přednášet o ASP.NET MVC na WebExpu, měl jsem zprvu strach. Nikdy jsem veřejně nepřednášel a z malých slideshow, které jsem dělal pro kolegy nebo ve škole, jsem si byl jistý, že mé prezentační schopnosti nejsou skoro žádné. Ale pak jsem si řekl, že zkusit bych to mohl, přinejmenším je to dobrá zkušenost a raději jsem požádal Borka, aby se ke mně přidal. Proč? Protože už jsem ho viděl přednášet na WebCampu a bylo to dobré.

Takže jsme se domluvili, že přednáška bude mít trochu širší záběr než jen ASP.NET MVC, které v té době bylo pouze v ukázkových verzích. V průběhu září jsme vymysleli nějakou osnovu, Borek založil SVN repository a začali jsme připravovat prezentaci.

Nejprve jsem udělal ukázku na využití ADO.NET Data Services ve spolupráci s ASP.NET AJAX (tu najdete přibalenou). Krom toho, že ukazuje základy konzumace RESTových Data Services, tak je i hezkou ukázkou toho, jak takové služby stavět nejen nad Entity Frameworkem, ale i nad ActiveRecord/NHi­bernate. No, ukázka není úplně dokončená, protože jsem se jí přestal věnovat a už jsem nenašel chuť jí dokončit, ale základní koncepce je snad pochopitelná – snažil jsem se vše okomentovat.

Osobně nemám rád psaní zbytečného kódu. Nejsem zastáncem zbytečných ukázkových aplikací, testovacích utilitek a tak. Takže už jsem žádné další ukázkové aplikace nepsal a rozhodl se další možnosti ASP.NET ukázat na již hotových aplikacích, se kterými mám něco společného.

Základní koncept komponent a Master pages jsem se tedy rozhodl ukázat – ať nechodíme daleko – na šabloně tohoto blogu. O něco pokročilejší komponentový framework jsem pak ukazoval na šabloně obchody.atlas.cz. Tahle jedna šablona je v podstatě celý web. Bez knihovny je sice mrtvá a ještě chyběj pravidla URL rewritingu, ale jinak je tam vše. Tyhle dvě ukázky najdete taktéž přibalené.

Poslední mou ukázkou byla aplikace, kterou jsem psal kvůli potřebě naučit se ASP.NET MVC a ADO.NET Data Services prakticky ještě před konferencí a zároveň abychom se v práci zbavili nutnosti zapisovat si příchody někam na papír (formulář) a pak na konci měsíce počítat, kolik kdo dostane stravenek :). Tak vznikla docházka a taky rozcestník projektů a tím pádem základ Twareg.Intranet. Shodou okolností to možná bude i naše první komerčně prodávaná aplikace. Hezký osud bokovky…

Takže na tomto webu jsem se pokusil ukázat, jak se dělá routing, jak je ten systém modulární. Jak deklarativně pomocí atributů nastavit autorizaci k akcím a jak akce snadno přejmenovat. Na víc už moc nezbýval čas. Tahle ukázka přibalená není. Namísto ní najdete Borkovy REST služby postavené nad ASP.NET MVC, které jsme bohužel nestihli ukázat.

Co se týče mého vystoupení, tak moc spokojený nejsem, vůbec se to nedostalo ani na spodní hranici mých představ o dobré přednášce – naštěstí tam byl Borek, aby to zachránil.

Author Stream ty slajdy trochu rozsypal, ale lepší než nic. Jinak pokud si chcete slajdy nebo ukázky stáhnout, pokračujte na Slajdy a ukázky z WebExpa. Pokud vás toto téma zajímá určitě najdete spoustu zajímavých futures bits na Codeplexu. Některá témata z přednášky bych rád rozebral podrobněji tady na blogu, ale až někdy jindy.

Shlédnuté prezentace

Na WebExpu jsem naštěstí nebyl jen jako pokus o přednášejícího, ale i jako divák. Oproti původnímu plánu jsem nakonec navštívil trochu jiné přednášky. Jako opravdu výbornou můžu označit přednášku Juraje Michálka o Flexu. Hodně dobrá byla nejspíš i Karmiho přednáška o Ruby on Rails, ale zastihl jsem jen asi posledních 25 min. Přednáška o Nette z úst nejzasvěcenějšího byla zábavná, nicméně s plánovaným školením PHP frameworky na paměti značně zredukovaná.

Mezi pro mě obsahově hodnotné a pořád dobře odprezentované bych ještě rád zařadil Dagiho přednášku o Springu, přednášku Vlastimila Pečínky o architektuře v Seznamu a přednášku o SproutCore od Antonína Hildebranda. Sice jsem nedostal odpověď na otázku, jestli to funguje i bez JavaScriptu, ale i tak přednášku hodnotím jako přínosnou a můžu rubistům tiše závidět ;).

Sociální vlivy

Na tuhle akci jsem nejvíc těšil hlavně kvůli lidem. Já moc na tydlety akce nechodím, ale jednou za čas se potkat s lidmi, které často čtu, není špatné. Rád jsem osobně potkal i některé nové tváře, které jsem dosud nečetl a třeba to napravím…

Na závěr

Na závěr patří především velíké díky Vaškovi, za velikou zkušenost, za zorganizování téhle veliké party se spostou zajímavých osobností a se širokým záběrem témat. Je dobré když se člověk může podívat na to jak to dělaj jinde a něčemu se třaba přiučit nebo prodiskutovat své pohledy na věc. Ono táhnout konferenci až do první hodiny ranní není žádná sranda. Respekt!

Jo a málem bych zapomněl, na LinkedIn jsem vytvořil k této konferenci skupinu, takže pokud jste se ještě do ní nepřidali, neváhejte a udělejte to ještě teď. A pokud vás zajímají slajdy ostatních nebo chcte nasdílet své, využijte eventu na slide share.