The official Fatica Labs Blog! RSS 2.0
# Wednesday, 22 December 2010

The hbm2net and db2hbm tool are now updated to the latest NH version. The fastest location for download are:

The solution on sourceforge now is updated to VS 2010.

Wednesday, 22 December 2010 10:39:01 (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
db2hbm | hbm2net | NHibernate

# Saturday, 04 December 2010

Ho appreso da un mio collega l’esistenza del comando unix/linux tail, che com il flag –f monitora costantemente un file e scrive a console le nuove linee aggiunte. Questo è ottimo se si sta seguendo realtime un log su file. L’unico problema di questa soluzione è che – almeno nell ‘ implementazione che abbiamo usato-  usando il RollingFileAppender di log4net il file rimaneva locked, e durante la rinomina automatica falliva e si rischiava di perdere comopletamente un segmento di log.

A tale scopo ho scritto una piccola utility C# che fa esattamente la stessa cosa di tail –f, che troavate su codeplex a questo indirizzo.

Una breve descrizione della command line:

 

  • tailf mylog.txt continuously dump on the console the content of mylog.txt as soon new lines are written into it.
  • tailf -n:15 mylog.txt continuously dump on the console the content of mylog.txt as soon new lines are written into it. At startup the last 15 lines are dumped.
  • tailf mylog.txt -f:ERROR continuously dump on the console the content of mylog.txt as soon new lines are written into it. Just lines containing "ERROR" are shown.
  • tailf mylog.txt -f:"ERROR|WARN" continuously dump on the console the content of mylog.txt as soon new lines are written into it. Just lines containing "ERROR" or "WARN" are shown; double quotes are necessary since | is a special char in the command shell.
Per avere invece al volo un idea di come usare il codice per altri scopi date un’ occhiata qui.
Saturday, 04 December 2010 06:04:53 (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
log4net

# Saturday, 30 October 2010
Saturday, 30 October 2010 09:27:14 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback


# Thursday, 28 October 2010

Questo simpatico errore è comparso dopo un upgrade da Windows 2003 Standard a Windows 2003 Enterprise. L’applicazione in oggetto è una appliactivo web che hosta dei servizi ashx, ma poco importa, si manifestava con qualsiasi richiesta IIS. La soluzione di questo problema consiste in pratica nell assegnare le permission all’utente  NETWORK SERVICE – o meglio, ritengo all’ utente che fa girare il worker process di IIS - alla cartella windows\temp, nonchè a  tutte le altre cartelle usate dall’applicativo ( xEs i log ). Stranamente prima dell’upgrade le permission c’erano ( l’applicativo era in produzione ) e funzionava bene.

Thursday, 28 October 2010 08:46:40 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback


# Saturday, 23 October 2010

Note: For visitors of your site, this entry is only displayed for users with the preselected language Romanian/română (ro)

Continuare la partea a 5-a

În această parte ne vom opri puţin să analizăm mai bine cum şi când se activează sesiunea (ISession) şi care sunt modalităţile cele mai corecte pentru a o face. Să vedem în mare ce face Session:

  1. Permite recuperarea, salvarea şi eliminarea entităţilor.
  2. Menţine un mapp al entităţilor organizat ca reference/ID Database
  3. Administrează un cache ( first level cache ) care, prin mapp-ul de mai sus, evită să meargă la baza de date pentru a recupera o entitate pe care o avem deja in memorie
  4. Ţine evidenţa entităţilor modificate
  5. Administrează interacţiunile cu driver-ul ADO.NET , inclusiv deschiderea închiderea conexiunilor.
  6. Ne permite să închidem şi să deschidem tranzacţiile.

Cel de-al doilea punct merită un comentariu: între diferenţele conceptuale dintre baza de date şi obiecte .Net există identitatea obiectului. În baza de date relaţia de identitate este după o ultimă analiză garantată de ID-ul rândului, în timp ce în .NET identitatea a două obiecte este după o ultimă analiză raportată la confruntarea dintre două reference. NHibernate vrea să evite existenţa acestor ambiguităţi şi susţine faptul că trebuie să existe o singură reference care să mizeze la un determinat obiect persistent: chiar dacă creăm un obiect clonă al unui obiect persistent şi incercăm, de exemplu să-l eliminăm sau să-l modificăm, această clonă nu va fi acceptată de NHibernate.

Practic când avem nevoie să interacţionăm cu obiectele persistent, avem necesitatea de a lucra în sfera unei sesiuni. Acest lucru introduce adesea nişte erori când căutăm momentul oportun pentru a deschide sesiunea:

 

Open Session: De evitat

1. De evitat deschiderea unei sesiuni pentru fiecare interacţiune pe care vrem să o avem cu stratul persistenţei ( Session-per-operation Antipattern )

2. De evitat utilizarea unei singure sesiuni pe întreaga durată a aplicaţiei. ( Session-per-application Antipattern ) Am mai spus acest lucru, dar e bine de amintit având în vedere că vorbim despre lucruri de evitat: dacă sesiunea are o anumită agilitate de uz, Session Factory trebuie să fie deschisă o singură dată în interiorul unui app domain. Nu pentru că ar exista ceva ce nu funcționează, dar pur şi simplu sesiunea factory se încarcă lent.

Dacă folosim prima strategie, ne lovim puternic de faptul că NH nu vrea să "mixeze" entităţi ce aparţin mai multor sesiuni, se pierde orice fel de beneficiu al cach-ului de prim nivel, iar obiectele lazy tind să producă cunoscuta eroare “NHibernate.LazyInitializationException: illegal access to loading collection”, datorită faptului că sesiunea care a creat obiectul a fost deja închisă, iar NH nu poate să meargă să recupereze obiectele colecţiei.

Cea de-a doua strategie este mai complicată: lucrăm cu date în "repaus", adică date ce probabil nu sunt aduse la zi cu respectivele obiecte salvate, sesiunea se îngreunează (NH devine din ce în ce mai lent dacă obiectele tratate de o sesiune sunt prea multe), nu se mai asigură o politică corectă de administrare a conexiunii la BD, care trebuie să fie deschisă doar pe timpul necesar, şi deci închisă.

Soluţia recomandată este Session per Business Transaction. O busuness transaction este, pentru a face un exemplu: „citesc prima pagină a clienţilor", "Introduc o nouă comandă", "Caut toate produsele ce încep cu XXX în depozit", etc. Deci operaţiuni autoincluse, dar nu triviale. În aplicaţii pot exista uşoare diferenţe între rich client şi Web application, în aceste din urmă realizarea acestui pattern poate converge în Session Per Request, ce constă în deschiderea unei sesiuni când se verifică evenimentul Begin request, şi închiderea acesteia la următorul End. Acest gen de contact, în general este aproape echivalent cu Session Per bussines transaction, pentru că de fapt, într-o aplicaţie web un ciclu request/response coincide cu o bussines transaction.

Putem folosi în acest scop patterm-ul Unit of Work. În sursele de exemplu am pus o versiune simplă, care utilizează ContextSession ale NH. Practic aceste Context session ne permit să împărtăşim o sesiune între mai multe funcţii ale aplicaţiei noastre, în realaţie cu un context ce poate fi, de exemplu Thread-ul curent, sau HttpContext-ul apelului la web server, sau oricare alt lucru, din punctul de vedere al configurării. Ca să ne fie mai clar, să vedem sursele:

 

 

   1: public class NHUow:IDisposable
   2: {
   3:     private NHUow()
   4:     {
   5:         if (CurrentSessionContext.HasBind(sessionFactory))
   6:             throw new InvalidOperationException("Nested unit of work not allowed.");
   7:         CurrentSessionContext.Bind(sessionFactory.OpenSession());
   8:     }
   9:     
  10:     static object lockObject = new object();
  11:     public static NHUow Open()
  12:     {
  13:         lock (lockObject)
  14:         {
  15:             if (sessionFactory == null)
  16:                 CreateSessionFactory();
  17:         }
  18:         return new NHUow();
  19:     }
  20:     public static ISession CurrentSession
  21:     {
  22:         get { return sessionFactory.GetCurrentSession(); }
  23:     }
  24:  
  25:     private static ISessionFactory sessionFactory;
  26:     private static void CreateSessionFactory()
  27:     {
  28:         Configuration cfg = CreateConfiguration();
  29:         sessionFactory = cfg.BuildSessionFactory();
  30:     }
  31:  
  32:     private static Configuration CreateConfiguration()
  33:     {
  34:         Configuration cfg = new Configuration();
  35:         cfg.Configure();
  36:         // implicitamente carichiamo tutti i mapping che si trovano nell'assembly che
  37:         // contiene customer
  38:         cfg.AddAssembly(typeof(Customer).Assembly);
  39:         return cfg;
  40:     }
  41:  
  42:  
  43:     #region IDisposable Members
  44:  
  45:     public void Dispose()
  46:     {
  47:         if (!CurrentSessionContext.HasBind(sessionFactory) )
  48:         {
  49:             throw new InvalidOperationException("Invalid current session");
  50:         }
  51:         var session = sessionFactory.GetCurrentSession();
  52:         CurrentSessionContext.Unbind(sessionFactory);
  53:         if (!session.IsOpen)
  54:         {
  55:             throw new InvalidOperationException("Session closed before UOW end");
  56:         }
  57:        
  58:         if ( null != session.Transaction && session.Transaction.IsActive )
  59:         {
  60:             if (session.Transaction.WasCommitted == false && session.Transaction.WasRolledBack == false)
  61:                 session.Transaction.Rollback();
  62:         }
  63:         session.Close();
  64:     }
  65:  
  66:     #endregion
  67: }

 

Obiectul implementează IDisposable, şi ne permite să-l utilizăm în acest fel:

 

   1: using (var uow = NHUow.Open())
   2: {
   3:     var transaction = NHUow.CurrentSession.BeginTransaction();
   4:     Customer c = new Customer();
   5:     c.Name = "FELIX";
   6:     c.AddressLine1 = c.AddressLine2 = "";
   7:     c.City = "XX";
   8:     c.ZipCode = "12060";
   9:     NHUow.CurrentSession.Save(c);
  10:     transaction.Commit();
  11: }

Practic deschid o unitate de lucru cu using new… şi, odată ieşiţi din scope, uow se închide. În interiorul acestui scope, întregul nostru cod va putea accesa sesiunea curentă folosind funcţia statică NHUow.CurrentSession. Cei mai atenţi vor observa faptul că configurarea sesiunii factory este fixă:acest lucru se întâmplă pentru a simplifica clasa UOW, pentru a o face să devină generală este de ajuns să intervenim adăugând o Session FactoryFactory, pe care UOW o va utiliza pentru a recupera Session factory - ul extern.

Dacă în acest moment am lansa unit testul de probă, am obţine următoarea excepţie:

No CurrentSessionContext configured (set the property current_session_context_class)!

Asta se întâmplă deoarece mecanismul de întreţinere al sesiunilor de context al NH este configurabil, iar noi nu am specificat nimic. După cum spune mesajul de eroare, trebuie să adăugăm în fişierul de config rândul current_session_context_class ( rândul 11 ):

   1: <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
   2:   <session-factory name="NHibernate.Test">
   3:     <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
   4:     <property name="connection.connection_string">Server=.\SQLEXPRESS;initial catalog=NHFROMSCRATCH;Integrated Security=SSPI</property>
   5:     <property name="adonet.batch_size">10</property>
   6:     <property name="show_sql">true</property>
   7:     <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
   8:     <property name="use_outer_join">true</property>
   9:     <property name="command_timeout">60</property>
  10:     <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
  11:     <property name="current_session_context_class">thread_static</property>
  12:     <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
  13:   </session-factory>
  14: </hibernate-configuration>

Observaţi că nu am introdus un nume al clasei, asta pentru că există anumite shortcut pentru cei mai folosiţi context manager. Enumerăm posibili context manager:

· NHibernate.Context.WebSessionContext – Sesiunea curentă este inclusă în HttpContext. Alias web.

· NHibernate.Context.CallSessionContext - Sesiunea curentă este inclusă în CallContext. Alias call.

· NHibernate.Context.ThreadStaticSessionContext – Sesiunea curentă este în context –ul thread-ului. Alias thread_static.

Desigur, tot cu filosofia maximei extensibilităţi, putem scrie context manager-ul nostru.

In sursele de exemplu, pe lângă clasa UOW, există o clasă a Unit Test-ului NHFromScratch.Tests.Uow , care arată cum se foloseşte.

 

Mergi la partea  5
Descarca Sursa
Saturday, 23 October 2010 18:47:18 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
hbm2net | NHibernate | NHibernate Tutorial

# Sunday, 17 October 2010

 Kynetic ORM è un nuovo ORM che sfrutta le potenzialità di C# 4.0, in particolare dynamics, per consentire un utilizzo a configurazione Zero. L’autore propone un esempio completo partendo da questo modello:

 

image

E mostrando come con qualche riga di codice si realizzi di fatto l’accesso:

 

 
   1: string cn = "your connection string";
   2: var link = new KSQLLink( cn );
   3: cmd = link.From( x => x.Employees ).Where( x => x.LastName >= "C" );
   4: foreach( dynamic obj in cmd ) Console.WriteLine( "- {0}\n", obj );
 
Ci sono comunque delle facilities se si vuole creare un mapping con oggetti fortemente tipati ( ma ovviamente il codice da scrivere aumenta :-; )

Mi sembra di poter dire che sia un progetto da seguire, anche se mi sento di dire che forse incoraggia un po’ troppo l’approccio DB-First.

Sunday, 17 October 2010 09:36:22 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
ORM

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2019
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 127
This blog visits
All Content © 2019, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano
Nike Winkels Nederland Outlet Nike Nederland Store Outlet Nike Nederland 2015 Outlet Nike Outlet Online Nike Sneakers Outlet