<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Marcin Wolański</title>
  <id>http://wolanski.info/feed.atom</id>
  <updated>2010-11-15T00:00:00Z</updated>
  <link href="http://wolanski.info/" />
  
  <subtitle type="text">Recent blog posts</subtitle>
  <generator>Werkzeug</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MarcinWolanski" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="marcinwolanski" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Trac na Windows</title>
    <id>http://wolanski.info/2010/11/15/trac-na-windows</id>
    <updated>2010-11-15T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/11/15/trac-na-windows" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Kiedy &lt;a class="reference external" href="http://blog.wolanski.info/2010/10/uzytkownicy-domenowi-w-visualsvn-server.html"&gt;VisualSVN Server zainstalowałem tak, jak chciałem&lt;/a&gt;, zachciało mi się systemu do zarządzania błędami. Padło na &lt;a class="reference external" href="http://trac.edgewall.org/"&gt;Trac&lt;/a&gt;. Do instalacji postanowiłem wykorzystać Apache VisualSVN Servera. Wiem, że mógłbym wziąć sobie paczkę z &lt;a class="reference external" href="http://www.visualsvn.com/files/VisualSVN-Server-Trac-2.1.1.21699.zip"&gt;Trac dla VisualSVN Server&lt;/a&gt;, ale nie zrobiłem tego, bo po pierwsze, nie zawiera najnowszej, stabilnej wersji Trac, a po drugie – niezależna instalacja Trac uprości aktualizację narzędzia w przyszłości.&lt;/p&gt;
&lt;div class="section" id="przygotowanie-srodowiska"&gt;
&lt;h2&gt;Przygotowanie środowiska&lt;/h2&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;Zainstalowałem po kolei używając defaultowych ścieżek:&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="first last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.activestate.com/activepython/downloads"&gt;ActivePython 2.5.5.7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c11.win32-py2.5.exe#md5=cb0cd7b844bed5106aeb0d4583848b1f"&gt;setuptools 0.6c11 dla Python 2.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://ftp.edgewall.com/pub/genshi/Genshi-0.6.win32.exe"&gt;Genshi 0.6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="&amp;quot;http://ftp.edgewall.com/pub/trac/Trac-0.12.win32.exe&amp;quot;"&gt;Trac 0.12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Niestety &lt;a class="reference external" href="http://subversion.tigris.org/files/documents/15/47858/svn-python-1.6.6.win32-py2.5.exe"&gt;najnowsze bindingi SVN dla Pythona 2.5&lt;/a&gt; nie pomogą w integracji Trac z VisualSVN Server (gdzieś znalazłem informację, że winne są zmodyfikowane biblioteki SVN w VisualSVN Server). Ale poradziłem sobie z tym pobierając wspomnianą paczkę &lt;a class="reference external" href="http://www.visualsvn.com/files/VisualSVN-Server-Trac-2.1.1.21699.zip"&gt;Trac dla VisualSVN Server&lt;/a&gt; i kopiując z archiwum katalogi &lt;em&gt;trac\python\Lib\site-packages\libsvn&lt;/em&gt; oraz &lt;em&gt;trac\python\Lib\site-packages\svn&lt;/em&gt; do &lt;em&gt;c:\Python25\Lib\site-packages&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="konfiguracja-trac"&gt;
&lt;h2&gt;Konfiguracja Trac&lt;/h2&gt;
&lt;p&gt;Z wiersza poleceń wykonujemy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;c:\Python25\Scripts\trac-admin.exe c:\trac initenv
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Na pytania instalatora odpowiadamy następująco:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Project Name: Moja_nazwa
Database connection string [sqlite:db/trac.db]: &amp;lt;enter&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do katalogu &lt;em&gt;c:\trac&lt;/em&gt; dajemy prawa do odczytu i zapisu użytkownikowi, na którym uruchomiona jest usługa.&lt;/p&gt;
&lt;p&gt;Na tym etapie można już uruchomić webserwer Traca poleceniem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;tracd --port 8000 c:\trac
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My chcemy jednak, żeby Trac serwowany był przez Apache. W związku z tym trzeba doinstalować &lt;a class="reference external" href="http://www.apache.org/dist/httpd/modpython/win/3.3.1/mod_python-3.3.1.win32-py2.5-Apache2.2.exe"&gt;mod_python dla Apache 2.2 i Python 2.5&lt;/a&gt;. Instalator zapyta nas, gdzie jest zainstalowany Apache. Chcemy wykorzystać serwer dostarczany razem z VisualSVN Server. W związku z tym tworzymy katalog &lt;em&gt;modules&lt;/em&gt; w &lt;em&gt;C:\Program Files\VisualSVN Server\bin&lt;/em&gt; i wskazujemy instalatorowi katalog &lt;em&gt;C:\Program Files\VisualSVN Server\bin&lt;/em&gt;, a w konfiguracji Apache &lt;em&gt;C:\Program Files\VisualSVN Server\conf\httpd.conf&lt;/em&gt; dodajemy linie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;LoadModule python_module bin/modules/mod_python.so
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dodajemy do konfiguracji Apache katalog Trac:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;/trac&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    SetHandler mod_python
    PythonInterpreter main_interpreter
    PythonHandler trac.web.modpython_frontend
    PythonOption TracEnv &amp;quot;C:/trac&amp;quot;
    PythonOption TracUriRoot /trac
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Chcemy, aby w Trac mogli się zalogować użytkownicy domenowi. W związku z tym w konfiguracji dodajemy jeszcze poniższy fragment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;/trac/login&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    AuthType SSPI
    AuthName &amp;quot;Trac&amp;quot;
    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain NAZWA_DOMENY
    SSPIOfferBasic Off
    Require valid-user
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pod adresem &lt;em&gt;http://nazwa_hosta//trac&lt;/em&gt; mamy dostęp do Trac.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=FK9H32DhXOE:cqcHpwIIYfg:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=FK9H32DhXOE:cqcHpwIIYfg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=FK9H32DhXOE:cqcHpwIIYfg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">External Tools w Visual Studio 2010 Express</title>
    <id>http://wolanski.info/2010/10/25/external-tools-w-visual-studio-2010-express</id>
    <updated>2010-10-25T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/10/25/external-tools-w-visual-studio-2010-express" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Zainstalowałem sobie Visual Studio 2010 Express. Jest kilka narzędzi, które
lubię mieć zdefiniowane jako External Tools. Wchodzę zwyczajowo w menu &lt;em&gt;Tools&lt;/em&gt;
i… nie ma opcji &lt;em&gt;External Tools&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Okazało się, że autorzy nie usunęli tego wielce przydatnego narzędzia, ale je
ukryli. Wystarczy włączyć opcję &lt;em&gt;Tools &amp;gt; Settings &amp;gt; Expert Settings&lt;/em&gt; i
&lt;em&gt;External Tools&lt;/em&gt; wrócą na swoje miejsce.&lt;/p&gt;
&lt;img alt="http://wolanski.info/static/images/20101025.png" src="http://wolanski.info/static/images/20101025.png" /&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=te1XhVCW-og:82nV9SbgGAA:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=te1XhVCW-og:82nV9SbgGAA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=te1XhVCW-og:82nV9SbgGAA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Użytkownicy domenowi w VisualSVN Server</title>
    <id>http://wolanski.info/2010/10/10/uzytkownicy-domenowi-w-visualsvn-server</id>
    <updated>2010-10-10T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/10/10/uzytkownicy-domenowi-w-visualsvn-server" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Korzystałem kiedyś z &lt;a class="reference external" href="http://www.visualsvn.com/server"&gt;VisualSVN Server&lt;/a&gt;, ale
wówczas wystarczała mi autoryzacja &lt;em&gt;Basic&lt;/em&gt;, czyli każdy użytkownik ma swoją nazwę i hasło. Rozwiązanie to jest niewygodne, jeśli działamy w ramach domeny Windows. Po co nowa nazwa i hasło użytkownika specjalnie dla Subversion?&lt;/p&gt;
&lt;p&gt;VisualSVN Server w darmowej wersji Standard Edition nie udostępnia możliwości zmiany sposobu autoryzacji użytkowników z poziomu konsoli serwera. Trzeba zakupić wersję Enterprise Edition za 950 dolarów. Jako, że nie znalazłem na stronie narzędzia informacji, że modyfikacja serwera jest niezgodna z licencją, postanowiłem spróbować zmusić darmową wersję do autoryzacji użytkowników domenowych.&lt;/p&gt;
&lt;p&gt;Ściągnąłem i zainstalowałem &lt;a class="reference external" href="http://www.visualsvn.com/files/VisualSVN-Server-2.1.4.msi"&gt;najnowszą wersję&lt;/a&gt; narzędzia (zachowałem defaultowe ustawienia instalatora).&lt;/p&gt;
&lt;p&gt;Aby móc skorzystać z logowania użytkowników domenowych w darmowej wersji
VisualSVN Server należy ściągnąć moduł &lt;a class="reference external" href="http://sourceforge.net/projects/mod-auth-sspi/"&gt;mod_auth_sspi&lt;/a&gt;. Archiwum rozpakowujemy do katalogu &lt;em&gt;C:\Program Files\VisualSVN Server\bin&lt;/em&gt;. Trzeba jeszcze zmienić konfigurację Apache znajdującą się w pliku &lt;em&gt;C:\Program Files\VisualSVN Server\conf&lt;/em&gt;. Deklarujemy załadowanie modułu:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;LoadModule&lt;/span&gt; sspi_auth_module bin/mod_auth_sspi.so
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;W tym samym pliku linie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;AuthType&lt;/span&gt; Basic
&lt;span class="nb"&gt;AuthBasicProvider&lt;/span&gt; file
&lt;span class="nb"&gt;AuthUserFile&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;C:/Repositories/htpasswd&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;zastępujemy następującymi:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;AuthType&lt;/span&gt; SSPI
&lt;span class="nb"&gt;SSPIAuth&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;SSPIAuthoritative&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;SSPIDomain&lt;/span&gt; NAZWA_DOMENY
&lt;span class="nb"&gt;SSPIOfferBasic&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Użytkownika o nazwie NAZWA_DOMENY\uzytkownik można dodać zarówno z poziomu
konsoli VisualSVN Server, jak i edytując plik &lt;em&gt;C:\Repositories\authz&lt;/em&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=5qDrBn3NG94:MCsp1jzljSA:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=5qDrBn3NG94:MCsp1jzljSA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=5qDrBn3NG94:MCsp1jzljSA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Wykorzystanie Rake do budowy projektu .NET</title>
    <id>http://wolanski.info/2010/10/06/wykorzystanie-rake-do-budowy-projektu-net</id>
    <updated>2010-10-06T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/10/06/wykorzystanie-rake-do-budowy-projektu-net" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Przy okazji rozpoczęcia nowego projektu chciałem w prosty sposób umożliwić budowę projektu z linii komend. Do tej pory używałem do tego NAnta, ale tym razem chciałem dać szansę narzędziu, z którego korzysta wiele projektów open-source: Rake.&lt;/p&gt;
&lt;p&gt;Wymagania miałem dwa: kompilacja projektu wykorzystującego .NET 4.0 oraz uruchomienie testów jednostkowych wykorzystujących bibliotekę &lt;a class="reference external" href="http://xunit.codeplex.com"&gt;xUnit.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Rozpocząłem od ściągnięcia i instalacji środowiska &lt;a class="reference external" href="http://rubyforge.org/frs/download.php/72170/rubyinstaller-1.9.2-p0.exe"&gt;Ruby dla Windows&lt;/a&gt;. Aby nie wynajdywać od nowa koła, zainstalowałem bibliotekę &lt;a class="reference external" href="http://albacorebuild.net"&gt;Albacore&lt;/a&gt;, która znacznie ułatwia pracę ze skryptem wykorzystywanym do budowy projektu .NET. Aby zainstalować Albacore, należy w wierszu poleceń uruchomić komendę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;gem install albacore
&lt;/pre&gt;&lt;/div&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;Mój projekt ma w uproszczeniu taką strukturę:&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="first last simple"&gt;
&lt;li&gt;MyApplication\lib&lt;/li&gt;
&lt;li&gt;MyApplication\lib\xunit-1.6.1&lt;/li&gt;
&lt;li&gt;MyApplication\source&lt;/li&gt;
&lt;li&gt;MyApplication\source\MySolution.sln&lt;/li&gt;
&lt;li&gt;rakefile.rb&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Aby nie musieć wskazywać w wywołaniu w wierszu poleceń narzędzia rake pliku ze
zadaniami, skrypt budujący projekt należy utworzyć w pliku o nazwie rakefile,
Rakefile, rakefile.rb lub Rakefile.rb. Ja wybrałem sobie nazwę &lt;em&gt;rakefile.rb&lt;/em&gt;. Dzięki temu, aby wywołać defaultowe zadanie dla Rake, będąc w katalogu projektu, w wierszu poleceń wystarczy wykonać komendę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;rake nazwa_zadania
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Na początku pliku &lt;em&gt;rakefile.rb&lt;/em&gt; deklarujemy użycie biblioteki Albacore:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;albacore&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Następnie dodajemy zadanie budujące solucję:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Build solution&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;msbuild&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_to_command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;windir&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.NET&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;Framework&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;v4.0.30319&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;MSBuild.exe&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="ss"&gt;:configuration&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:Debug&lt;/span&gt;
    &lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt; &lt;span class="ss"&gt;:Clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:Build&lt;/span&gt;
    &lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;source/MySolution.sln&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pierwsza linijka zawiera opis zadania i ma tylko znaczenie dokumentujące. W
drugiej linii &lt;em&gt;msbuild&lt;/em&gt; oznacza nazwę zadania z Albacore, a &lt;em&gt;:build&lt;/em&gt; alias dla tego zadania. Dzięki temu, aby zbudować projekt, w wierszu poleceń należy wykonać komendę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;rake build
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Jeśli pominąłbym alias, to budowę solucji mógłbym uruchomić tak:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;rake msbuild
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Trzecia linia nie wygląda najlepiej, ale jest niestety konieczna, jeśli projekt używa .NET 4.0. A to dlatego, że zadanie msbuild z Albacore domyślnie używa .NETa 3.5 i wykonanie go, bez zdefiniowania ścieżki do msbuild.exe z właściwego frameworka, zakończy się błędem.&lt;/p&gt;
&lt;p&gt;Pozostała część kodu zadania jest oczywista: chcemy zbudować solucję MySolution.sln w trybie Debug, uprzednio robiąc porządki.&lt;/p&gt;
&lt;p&gt;Zadanie uruchomienia testów jednostkowych jest krótkie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Run unit tests&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;xunit&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;xunit&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;xunit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_to_command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;lib/xunit-1.6.1/xunit.console.clr4.exe&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;xunit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;unit_tests_file.dll&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podajemy ścieżkę do narzędzia uruchamiającego z wiersza poleceń testy jednostkowe wykorzystujące bibliotekę xUnit.net i wskazujemy bibliotekę z naszymi testami.&lt;/p&gt;
&lt;p&gt;Aby uruchomić testy jednostkowe, w wierszu poleceń należy wykonać komendę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;rake test
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Jeśli mamy jakieś zadanie, które wykonujemy wyjątkowo często, to przed definicją zadań można dodać linię:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:nazwa_lub_alias_zadania&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dzięki temu, aby wykonać to zadanie, w wierszu poleceń wystarczy wywołać komendę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;rake
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nie bawiłem się zbyt długo tym rozwiązaniem, ale póki co, przynajmniej dla mnie, nie ma porównania czytelność skryptu napisanego w Ruby z plikami dla NAnta czy też msbuilda. Chcę jeszcze dodać kilka różnych zadań i zintegrować wszystko z narzędziem CI. Zobaczymy, czy się uda.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=KaTpTzrDPrY:HhkDwm-AmBo:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=KaTpTzrDPrY:HhkDwm-AmBo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=KaTpTzrDPrY:HhkDwm-AmBo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Recenzja: Debugowanie. Jak wyszukiwać i naprawiać błędy w kodzie oraz im zapobiegać</title>
    <id>http://wolanski.info/2010/09/30/recenzja-debugowanie-jak-wyszukiwac-i-naprawiac-bledy-w-kodzie-oraz-im-zapobiegac</id>
    <updated>2010-09-30T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/09/30/recenzja-debugowanie-jak-wyszukiwac-i-naprawiac-bledy-w-kodzie-oraz-im-zapobiegac" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Debugowanie jest procesem niezwykle złożonym. &lt;a class="reference external" href="http://www.amazon.com/Debugging-Applications-Microsoft-Windows-Pro-Developer/dp/0735615365"&gt;Istnieją&lt;/a&gt; &lt;a class="reference external" href="http://www.amazon.com/Advanced-NET-Debugging-Mario-Hewardt/dp/0321578899"&gt;publikacje&lt;/a&gt;
opisujące techniczne aspekty wyszukiwania błędów w kodzie w ten właśnie sposób.
Czasami warto jednak zapoznać się z jakimś zagadnieniem w oderwaniu się od konkretnej technologii. Taką właśnie pozycją jest &lt;a class="reference external" href="http://helion.pl/ksiazki/debugowanie_jak_wyszukiwac_i_naprawiac_bledy_w_kodzie_oraz_im_zapobiegac_paul_butcher,debugo.htm"&gt;Debugowanie. Jak wyszukiwać i naprawiać błędy w kodzie oraz im zapobiegać&lt;/a&gt; (oryg. &lt;a class="reference external" href="http://www.amazon.com/Debug-Repair-Prevent-Pragmatic-Programmers/dp/193435628X"&gt;Debug It!: Find, Repair, and Prevent Bugs in Your Code&lt;/a&gt;).&lt;/p&gt;
&lt;img alt="http://wolanski.info/static/images/20100930_01.jpg" src="http://wolanski.info/static/images/20100930_01.jpg" /&gt;
&lt;p&gt;Książka nie jest opisem jakiegoś narzędzia wspomagającego debugowanie, platformy uruchomieniowej czy też języka programowania (kodu jest bardzo niewiele). Autor skupił się raczej na mentalnym podejściu programisty do wyszukiwania błędów w aplikacji.&lt;/p&gt;
&lt;p&gt;Książka składa się z 3 części: &lt;em&gt;Istota problemu&lt;/em&gt;, &lt;em&gt;Szersza perspektywa&lt;/em&gt; oraz
&lt;em&gt;Debug-Fu&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;W części pierwszej autor opisuje metodę empiryczną debugowania tj. reprodukcję błędów, diagnozowanie ich przyczyny, poprawki oraz refleksja nad tym, co zrobić, aby w przyszłości nie musieć usuwać takich samych usterek.&lt;/p&gt;
&lt;p&gt;Część druga poświęcona jest miejscu debugowania w całym procesie tworzenia aplikacji m.in. współpracy z użytkownikami aplikacji, innymi zespołami, czy błędy powinny być naprawiane od razu po ich stwierdzeniu, czy może lepiej dodać jakąś nową funkcjonalność itd.&lt;/p&gt;
&lt;p&gt;W części trzeciej autor skupił się na technicznym aspekcie procesu debugowania: stworzeniu odpowiedniego środowiska umożliwiającego skuteczne debugowanie, systemach kontroli wersji, ciągłej integracji, testach jednostkowych, użyteczności asercji, kontraktów i bibliotek ułatwiających logowanie itd.&lt;/p&gt;
&lt;div class="section" id="podobalo-mi-sie"&gt;
&lt;h2&gt;Podobało mi się&lt;/h2&gt;
&lt;p&gt;Książki podejmujące tematykę debugowania od strony technicznej nie są, przynajmniej dla mnie, lekką lekturą. Trzeba znaleźć wolną chwilę, aby wiedzę zgłębiać w skupieniu i koniecznie przy komputerze. Opisywana pozycja ma tą cechę, że takich fragmentów jest naprawdę niewiele.&lt;/p&gt;
&lt;p&gt;Dodatkowo jej gabaryty zdecydowanie nie przeszkadzają w czytaniu np. w drodze do pracy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="nie-podobalo-mi-sie"&gt;
&lt;h2&gt;Nie podobało mi się&lt;/h2&gt;
&lt;p&gt;Choć tematyka książki sugeruje, że powinno się ją czytać lekko i przyjemnie, to tak niestety nie było w moim przypadku. Nie czytałem oryginału, ale wydaje mi się, że to kwestia przekładu.&lt;/p&gt;
&lt;p&gt;Dawno nie czytałem nic wydawanego przez &lt;a class="reference external" href="http://helion.pl"&gt;Helion&lt;/a&gt;. Zraziły
mnie do tego skutecznie przede wszystkim nieudane tłumaczenia. Do zakupu opisywanej pozycji skusiła mnie cena dużo niższa niż w &lt;a class="reference external" href="http://www.amazon.com"&gt;Amazon&lt;/a&gt;. Następnym razem się zastanowię, bo w tym przypadku skąpstwo nie popłaciło.&lt;/p&gt;
&lt;p&gt;Moim zdaniem nie powinno się tłumaczyć niektórych angielskich zwrotów. “Zaślepki testowe” (ang. test doubles), “atrapy” (ang. mocks), “namiastki” (ang. stubs) czy też mój ulubiony “profilator” (ang. profiler), to tylko niektóre kwiatki.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="czego-sie-nauczylem"&gt;
&lt;h2&gt;Czego się nauczyłem&lt;/h2&gt;
&lt;p&gt;Lubię od czasu do czasu przeczytać trochę mniej techniczną książkę. Lektura
&lt;em&gt;Debugowania…&lt;/em&gt; zmusiła mnie do refleksji nad tym, czy w codziennej pracy właściwie podchodzę do procesu diagnozy przyczyn błędów w rozwijanych i utrzymywanych aplikacjach.&lt;/p&gt;
&lt;p&gt;Polecam, ale raczej w języku angielskim.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=1Ires0Rg4sI:vgtPgEVx09E:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=1Ires0Rg4sI:vgtPgEVx09E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=1Ires0Rg4sI:vgtPgEVx09E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Zaznaczanie błędów w Visual Studio a deinstalacja Resharpera</title>
    <id>http://wolanski.info/2010/09/24/zaznaczanie-bledow-w-visual-studio-a-deinstalacja-resharpera</id>
    <updated>2010-09-24T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/09/24/zaznaczanie-bledow-w-visual-studio-a-deinstalacja-resharpera" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Po odinstalowaniu Resharpera zauważyłem, że w edytorze nie są zaznaczane błędy. Chwila grzebania w opcjach i udało się doprowadzić Visual Studio do stanu sprzed instalacji narzędzia.&lt;/p&gt;
&lt;p&gt;Wystarczy wybrać &lt;strong&gt;Tools&lt;/strong&gt; &amp;gt; &lt;strong&gt;Options&lt;/strong&gt; &amp;gt; &lt;strong&gt;Text Editor&lt;/strong&gt; &amp;gt; &lt;strong&gt;C#&lt;/strong&gt; &amp;gt;
&lt;strong&gt;Advanced&lt;/strong&gt; i zaznaczyć w &lt;strong&gt;Editor Helper&lt;/strong&gt; opcje &lt;em&gt;Underline errors in the
editor&lt;/em&gt; oraz &lt;em&gt;Show live semantic errors&lt;/em&gt;.&lt;/p&gt;
&lt;img alt="http://wolanski.info/static/images/20100924.png" src="http://wolanski.info/static/images/20100924.png" /&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=fMoKkCGoO-Q:gGe1544O3uk:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=fMoKkCGoO-Q:gGe1544O3uk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=fMoKkCGoO-Q:gGe1544O3uk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">NHibernate i wyjątki ADO</title>
    <id>http://wolanski.info/2010/03/03/nhibernate-i-wyjatki-ado</id>
    <updated>2010-03-03T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/03/03/nhibernate-i-wyjatki-ado" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Próba zapisania obiektu naruszającego więzy integralności przy użyciu biblioteki NHibernate spowoduje wygenerowanie wyjątku GenericADOException. Dopiero sięgając do wartości właściwości InnerException możemy przekonać się, co jest przyczyną niepowodzenia. Istnieje jednak sposób na zastąpienie standardowego wyjątku własnym.&lt;/p&gt;
&lt;p&gt;W przykładzie użyję prostej klasy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;i mapowania:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMap&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ClassMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Próba zapisu dwóch użytkowników o tej samej nazwie kończy się wyjątkiem GenericADOException:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="na"&gt;[Test, ExpectedException(typeof(NHibernate.Exceptions.GenericADOException))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CannotAddTwoUsersWithTheSameUsername&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataAccessFacade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenSession&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginTransaction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Oczywiście można sprawdzić, co jest przyczyną błędu przy zapisie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataAccessFacade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenSession&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginTransaction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericADOException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InnerException&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;SQLiteException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sqLiteException&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLiteException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InnerException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqLiteException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;SQLiteErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Constraint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;// do something with constaint exception&lt;/span&gt;
                &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Jednak ten sposób uzależniamy nasz kod od konkretnego providera. Ewentualna zmiana silnika bazy danych powoduje konieczność zmian w wielu klasach warstwy dostępu do danych. Poza tym obsługa wydawałoby się trywialnego problemu wymaga każdorazowo napisania wielu linii kodu.&lt;/p&gt;
&lt;p&gt;Czy powyższy fragment nie mógłby wyglądać tak:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;janKowalski2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Jan Kowalski&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DataAccessFacade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenSession&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginTransaction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;janKowalski2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConstraintViolationException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// do something with constaint exception&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O ile krócej, prawda? I nie obchodzi nas, że w danej chwili wykorzystujemy bazę danych SQLite, Oracle czy MSSQL Server.&lt;/p&gt;
&lt;p&gt;Aby osiągnąć ten efekt używając NHibernate, musimy stworzyć własną implementację interfejsu ISQLExceptionConverter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCustomSQLExceptionConverter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ISQLExceptionConverter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="nf"&gt;Convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AdoExceptionContextInfo&lt;/span&gt; &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ADOExceptionHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtractDbException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SqlException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SQLiteException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;SQLiteErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Constraint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt;
                        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NHibernate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConstraintViolationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InnerException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="k"&gt;null&lt;/span&gt;
                        &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SQLStateConverter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandledNonSpecificException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SqlException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;adoExceptionContextInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sql&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Metoda ADOExceptionHelper.ExtractDbException wyłuskuje pierwszy wyjątek System.Data.Common.DbException z drzewa wraz z jego InnerExceptionami. Reszta jest chyba oczywista.&lt;/p&gt;
&lt;p&gt;Konfigurujemy jeszcze NHibernate w pliku konfiguracyjnym:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sql_exception_converter&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    NameSpace.MyCustomSQLExceptionConverter, AssemblyName
&lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;albo za pomocą Fluent NHibernate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;_configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;NHibernate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SqlExceptionConverter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyCustomSQLExceptionConverter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;AssemblyQualifiedName&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=kRtld-0uGJ8:iimTRqTJrjM:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=kRtld-0uGJ8:iimTRqTJrjM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=kRtld-0uGJ8:iimTRqTJrjM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">NHibernate.Validator: komunikaty przyjazne dla użytkownika</title>
    <id>http://wolanski.info/2010/01/16/nhibernate-validator-komunikaty-przyjazne-dla-uzytkownika</id>
    <updated>2010-01-16T00:00:00Z</updated>
    <link href="http://wolanski.info/2010/01/16/nhibernate-validator-komunikaty-przyjazne-dla-uzytkownika" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Jakiś czas temu przedstawiłem &lt;a class="reference external" href="http://wolanski.info/2009/10/31/nhibernate-validator-windows-forms-i-errorprovider/"&gt;sposób użycia biblioteki NHibernate.Validator w
aplikacji Windows Forms&lt;/a&gt;. Miał on jedną zasadniczą wadę: komunikaty walidatora były takie, jakie stworzyli autorzy biblioteki.&lt;/p&gt;
&lt;p&gt;Przypomnę, że &lt;a class="reference external" href="http://wolanski.info/2009/10/29/nhibernate-validator-i-windows-forms/"&gt;poprzednio&lt;/a&gt; stworzyliśmy użytkownika z właściwościami: imię, nazwisko i wiek. Założyliśmy, że imię i nazwisko nie mogą być puste i użytkownik musi mieć przynajmniej 18 lat:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ValidationDef&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreaterThanOrEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Niewypełnienie imienia i nazwiska skutkowało niskopoziomowym komunikatem: &lt;em&gt;nie
może być nieokreślony i pusty&lt;/em&gt;, natomiast wpisanie wieku mniejszego niż 18:
&lt;em&gt;musi być większe lub równe od 18&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Chciałbym, aby komunikaty były bardziej przyjazne dla użytkownikowa np. &lt;em&gt;Imię
jest wymagane&lt;/em&gt; czy też &lt;em&gt;Wiek musi być większy lub równy 18&lt;/em&gt;. Można dostosować komunikaty dla każdej reguły:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ValidationDef&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Imię jest wymagane.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Nazwisko jest wymagane.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreaterThanOrEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Wiek musi być większy lub równy 18.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Rozwiązanie jest zadowalające dla niewielkiej aplikacji. W bardziej skomplikowanej kosmetyczna zmiana &lt;em&gt;jest wymagane&lt;/em&gt; na &lt;em&gt;musi być wypełnione&lt;/em&gt; wymaga przejrzenia i aktualizacji kilku/kilkunastu/kilkudziesięciu klas. Autorzy przewidzieli taki przypadek: komunikaty można zdefiniować w zewnętrznym pliku zasobów.&lt;/p&gt;
&lt;p&gt;Dodajmy plik zasobów do projektu:&lt;/p&gt;
&lt;img alt="Przykładowy projekt" src="http://wolanski.info/static/images/20100116_01.png" /&gt;
&lt;p&gt;Definiujemy komentarze przyjazne dla użytkownika:&lt;/p&gt;
&lt;img alt="Zasoby" src="http://wolanski.info/static/images/20100116_02.png" /&gt;
&lt;p&gt;Obrazek chyba nie wymaga wyjaśnień, może poza &lt;em&gt;{Value}&lt;/em&gt; w komunikacie &lt;em&gt;message.user.age.GreaterThanOrEqualTo&lt;/em&gt;. Jest to właściwość publiczna atrybutu &lt;a class="reference external" href="https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/src/NHibernate.Validator/src/NHibernate.Validator/Constraints/MinAttribute.cs"&gt;MinAttribute&lt;/a&gt; wykorzystywanego w metodzie GreaterThanOrEqualTo. Dzięki temu argument wspomnianej metody będzie przekazywany do komunikatu. Jeśli zmieni się wartość dopuszczalnego wieku, wystarczy edycja reguły bez konieczności uaktualniania pliku z komunikatami.&lt;/p&gt;
&lt;p&gt;Zmieńmy klasę UserValidationDef tak, aby wykorzystywała komunikaty z pliku zasobów:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ValidationDef&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{message.user.firstname.NotNullableAndNotEmpty}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotNullableAndNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{message.user.lastname.NotNullableAndNotEmpty}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreaterThanOrEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{message.user.age.GreaterThanOrEqualTo}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ostatni krok, to konfiguracja biblioteki tak, aby wykorzystywał plik zasobów ValidationMessages.resx:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedEngineProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NHibernateSharedEngineProvider&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FluentConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetCustomResourceManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;NHVWinForms.Properties.ValidationMessages&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserValidationDef&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidationDefinitions&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetDefaultValidatorMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ValidatorMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseExternal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ve&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedEngineProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetEngine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I mamy przyjazne i łatwo modyfikowalne komunikaty: &lt;em&gt;Imię jest wymagane&lt;/em&gt; zamiast &lt;em&gt;nie może być nieokreślony i pusty&lt;/em&gt; i &lt;em&gt;Wiek musi być większy lub równy 18&lt;/em&gt; zamiast &lt;em&gt;musi być większe lub równe od 18&lt;/em&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=OdrE1R4vXwo:xb-L3OHl3zY:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=OdrE1R4vXwo:xb-L3OHl3zY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=OdrE1R4vXwo:xb-L3OHl3zY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Mapowanie bool na...</title>
    <id>http://wolanski.info/2009/12/10/mapowanie-bool-na</id>
    <updated>2009-12-10T00:00:00Z</updated>
    <link href="http://wolanski.info/2009/12/10/mapowanie-bool-na" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;W Oracle nie ma możliwości przechowywania wartości typu bool. Najbardziej
powszechnym rozwiązaniem jest użycie kolumny typu CHAR(1) z wartościami 'Y' i
'N'. Autorzy &lt;a class="reference external" href="http://nhforge.org/Default.aspx"&gt;NHibernate&lt;/a&gt; się na to
przygotowali udostępniając typ &lt;a class="reference external" href="http://www.nhforge.org/doc/nh/en/#mapping-types-basictypes"&gt;YesNo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mój przypadek był inny. Z bazy danych korzystała już aplikacja, która wartości
typu bool zapisywała w kolumnach typu INT. Wartość true zdefiniowana była jako
-1, wartość false - 0. Moja miała robić tak samo. Da radę. Tylko niestety
trzeba się trochę napisać.&lt;/p&gt;
&lt;p&gt;Tworzymy klasę MyTrueFalseType implementującą interfejs
NHibernate.Types.IUserType:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NHibernate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NHibernate.SqlTypes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NHibernate.UserTypes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyNamespace&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTrueFalseType&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IUserType&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;TRUE_VALUE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;FALSE_VALUE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;Assemble&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;DeepCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;Disassemble&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;GetHashCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetHashCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsMutable&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;NullSafeGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDataReader&lt;/span&gt; &lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NHibernateUtil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NullSafeGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;TRUE_VALUE&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;FALSE_VALUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ADOException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Expected data to be {0} or {1} but was {2}.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;TRUE_VALUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FALSE_VALUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boolValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TRUE_VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;NullSafeSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDbCommand&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;IDataParameter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DBNull&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;IDataParameter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                    &lt;span class="n"&gt;boolValue&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;TRUE_VALUE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FALSE_VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;ReturnedType&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;SqlType&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;SqlTypes&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;SqlTypeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dla przykładowej klasy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BaseEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Editable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;definiujemy mapowanie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClassMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ClassMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyClassMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;GeneratedBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HiLo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;UnsavedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Editable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;CustomType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyTrueFalseType&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;my_class&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Od teraz w tabeli &lt;em&gt;my_class&lt;/em&gt; w kolumnie &lt;em&gt;editable&lt;/em&gt; wartość true będzie zapisywana jako -1, wartość false jako 0.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=tPoyxhEr3W8:myMMcAXlub0:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=tPoyxhEr3W8:myMMcAXlub0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=tPoyxhEr3W8:myMMcAXlub0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
  <entry xml:base="http://wolanski.info/feed.atom">
    <title type="text">Własne połączenie w NHibernate</title>
    <id>http://wolanski.info/2009/11/26/wlasne-polaczenie-w-nhibernate</id>
    <updated>2009-11-26T00:00:00Z</updated>
    <link href="http://wolanski.info/2009/11/26/wlasne-polaczenie-w-nhibernate" />
    <author>
      <name>Marcin Wolański</name>
    </author>
    <content type="html">&lt;p&gt;Może czasem się zdarzyć, że chcemy użyć &lt;a class="reference external" href="http://nhforge.org/"&gt;NHibernate&lt;/a&gt;, jednak aplikacja korzysta z jakiegoś
frameworka, który ma już swoją definicję połączenia z bazą danych. Po co więc w
NHibernate ponownie konfigurować to samo połączenie, skoro można wykorzystać
już istniejące?&lt;/p&gt;
&lt;p&gt;Rozszerzamy klasę DriverConnectionProvider i w przeciążonej metodzie
GetConnection zwracamy połączenie pobrane z jakiegoś zewnętrznego mechanizmu:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDriverConnectionProvider&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NHibernate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DriverConnectionProvider&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;IDbConnection&lt;/span&gt; &lt;span class="nf"&gt;GetConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MyExternalFramework&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetConnection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wystarczy teraz odpowiednio skonfigurować NHibernate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Fluently&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OracleClientConfiguration&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Oracle10&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;My.Library.MyDriverConnectionProvider, My.Library&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;my_instance&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProxyFactoryFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@&amp;quot;NHibernate.ByteCode.Castlei&lt;/span&gt;
&lt;span class="s"&gt;                .ProxyFactoryFactory, NHibernate.ByteCode.Castle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mappings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FluentMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddFromAssemblyOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyClassMap&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BuildConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Niestety definicja ConnectionString jest niezbędna. Inaczej dostaniemy wyjątek
z informacją, że nasza konfiguracja jest niekompletna i brakuje właśnie
connection stringa.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=O5hlcPGd1Wk:2cfDqeHx__U:0VBWazUhMmc"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?d=0VBWazUhMmc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/MarcinWolanski?a=O5hlcPGd1Wk:2cfDqeHx__U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MarcinWolanski?i=O5hlcPGd1Wk:2cfDqeHx__U:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>
  </entry>
</feed>

