SlideShare une entreprise Scribd logo
1  sur  13
Télécharger pour lire hors ligne
TheServerSide.NET - Print Friendly                                                                                          Página 1 de 13




   NHibernate                                                                                                    Discuss     Printer friendly




  August 12, 2004

  Chances are, as a .NET developer, you are already intimately familiar with the ADO.NET dataset. If you are an “enterprise” developer,
  those odds approach 100%. Database interaction via the FCL centers around retrieving a static snapshot of some portion of the
  database and manipulating it via the dataset, which mimics the RDBMS in almost every way: the data is tabular, relationships between
  data are modeled by foreign keys, data is largely untyped. Since the dataset provides a static, in-memory cache of data, it makes the
  manipulation of that data much more efficient than requiring constant round trips to the live data store.

  The problem with the dataset is that it doesn’t fit particularly well with modern object-oriented application design. Whereas datasets
  have tabular data, we tend to code using objects. Datasets have foreign key relationships, our domain objects use references. Where we
  want to use only methods, datasets require a certain amount of SQL code. Of course, some of these problems can be solved through the
  use of “strongly typed” datasets, but the fact remains that you are changing modes as you move from your domain model to your data
  access and back again. Depending on how you choose to layer that data access code into the application, changes to the data store can
  have enormous ripple-effects on your codebase.

  Last month, Bruce Tate and I released a new book called “Better, Faster, Lighter Java”. Don’t let that “j” word in the title throw you too
  much; the principles we espouse in the book are equally applicable to any modern development platform. One of those principles is
  transparency; the key to any enterprise application is the domain model. These are the classes that model, and solve, your
  customers’ business problems. If you customer is a bank, your domain model is filled with Accounts, Deposits and Loans. If your
  customer is a travel agent, your domain is filled with Tours and Hotels and Airlines. It is in these classes that your customers’ problems
  are addressed; everything else is just a service to support the domain. I mean things like data storage, message transport, transactional
  control, etc. As much as possible, you want those services to be transparent to your domain model. Transparency means that your
  model benefits from those services without being modified by them. It shouldn’t require special code in your domain to utilize those
  services, it shouldn’t require specific containers, or interfaces to implement. Which means that your domain architecture can be 100%
  focused on the business problem at hand, not technical problems outside the business. A side effect of achieving transparency is that
  you can replace services with alternate providers or add new services without changing your domain.

  Coding directly against the dataset breaks the transparency. It is obvious inside of your code what storage mechanism you use, and it
  affects the way your code is written. Another approach to storage is the use of an object-relational mapping tool. Microsoft is in the
  process of building such a framework, called ObjectSpaces, but recently announced it would be delayed until as far as 2006.
  NHibernate, an open source solution, is available today and solves the same set of problems. With NHibernate, your code and your
  data schema remain decoupled, and the only visible indicator of the existence of the O/R layer are the mapping files. With HNibernate,
  you’ll see that these consist of configuration settings for the O/R framework itself (connecting to a data source, identifying the data
  language, etc.) and mapping your domain objects to the data tables.

  There are a variety of other O/R frameworks available today, some commercial and some open source. For the purposes of this article,
  though, we’ll focus on NHibernate. It has a lot of momentum carrying over from the Java side of the world, and is extremely easy to get
  started with. However, if the general techniques we see in this article appeal to you, I suggest you take a look at the other options
  available to see if others are a better fit for your needs.

  To get started, you’ll need to download the framework at http://nhibernate.sourceforge.net. Reference the assembly in your project.
  The next step will be to add the appropriate configuration settings to your application’s config file to tell NHibernate where and what
  your data store is. For the purposes of this article, we’ll use Microsoft SQL Server, though you could just as easily target Oracle,
  MySQL, or any number of other vendors. To map to a SQL Server instance, here is what your configuration settings might look like:




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                            15/10/2004
TheServerSide.NET - Print Friendly                                                                                             Página 2 de 13


  <configuration>
     <configSections>
           <section
              name=quot;nhibernatequot;
              type=quot;System.Configuration.NameValueSectionHandler, System,
                             Version=1.0.5000.0,Culture=neutral,
                             PublicKeyToken=b77a5c561934e089quot; />
     </configSections>

     <nhibernate>
           <add
              key=quot;hibernate.connection.providerquot;
              value=quot;NHibernate.Connection.DriverConnectionProviderquot;
           />
           <add
              key=quot;hibernate.dialectquot;
              value=quot;NHibernate.Dialect.MsSql2000Dialectquot;
           />
           <add
              key=quot;hibernate.connection.driver_classquot;
              value=quot;NHibernate.Driver.SqlClientDriverquot;
           />
           <add
              key=quot;hibernate.connection.connection_stringquot;
              value=quot;Server=localhost;initial catalog=nhibernate;User
                             ID=someuser;Password=somepwd;Min Pool Size=2quot;
           />
           </nhibernate>
  </configuration>


  Once you have configured the framework to recognize your data store, the next step is to create your domain model and database
  representation. It is entirely plausible to do those steps in either order – if your application is depending on a highly efficient storage
  schema, perhaps starting there is appropriate. However, if the database is just a place to store object state, then it probably makes
  more sense to start in the domain classes. There is a third option – start with the mapping files that will describe the relationships
  between your classes and tables. NHibernate provides a tool today that can auto-generate DDL from your mapping files. A recent
  addition to the project is a NAnt task that will auto-generate C# stubs from the mapping files. Taken together, you can adequately
  construct a base implementation by just coding up the mappings and letting NHibernate’s tools take care of the rest. NHibernate
  provides a tool today that can auto-generate DDL from your mapping files. A recent addition to the project is a NAnt task that will
  auto-generate C# stubs from the mapping files. Taken together, you can adequately construct a base implementation by just coding up
  the mappings and letting NHibernate’s tools take care of the rest.

  The Domain Model
  We’ll start with the domain model. For this article, we’ll tackle just a narrow segment of a larger enterprise application. Specifically,
  we’ll look at part of a university registration system. For our purposes, we’ll examine the following classes:

     1.   Department: describes one segment of the University’s curriculum.
     2.   UniversityClass: one class offered at the school (the funky name is to prevent using a reserved word as the name of the
          class).
     3.   Professor: person who teaches a class.
     4.   Student: person who takes a class.

  Each of these classes has its own data fields, but the relationships between them are where the fun starts.




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                              15/10/2004
TheServerSide.NET - Print Friendly                                                                                          Página 3 de 13




  A department can contain zero, one or more professors. A professor can be associated with more than one department. A department
  contains one or more classes. A class belongs to only one department. A class is taught by a single professor, but a professor can teach
  multiple classes. Many students can take a single class, and students (should) take more than one class. There is no direct relationship
  between students and departments or professors (any relationship between student and professor is probably illegal, anyway).

  Our domain objects are fairly straightforward. Here’s the list of classes and their data fields:

              public class Department
              {
                       private int id;
                       private string name;
                       private IDictionary classes;
                       private IDictionary professors;
              }

              public class Professor : Person
              {
                       private int id;
                       private string firstname;
                       private string lastname;
                       private string id;
                       private IDictionary departments;
                       private IDictionary classes;
              }

              public class UniversityClass
              {
                       private int id;
                       private string name;
                       private string number;
                       private string syllabus;
                       private DateTime startDate;
                       private Professor professor;
                       private IDictionary students;
                       private Department department;
              }

              public class Student : Person




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                           15/10/2004
TheServerSide.NET - Print Friendly                                                                                            Página 4 de 13


              {
                           private    int id;
                           private    string firstname;
                           private    string lastname;
                           private    string ssn;
                           private    IDictionary classes;
              }



              public interface Person
              {
                       public int Id;
                       public string FirstName;
                       public string LastName;
              }


  Of course, you’ll probably want to provide public properties to wrap those fields, as it is good coding practice. Though NHibernate can
  work directly with private and protected fields, it just generally makes more sense to use properties for field access.

  Secondly, remember that our Professor and Student classes will share a table. In the domain, they share several data fields as
  well (FirstName, LastName and ID). In our domain model, we represent this relationship through some form of inheritance. In
  this case, they both implement the Person interface, as shown.

  Finally, you will see that our collection fields are all defined using IDictionary. When defining your collections in your domain, stick to
  the interfaces provided for you in System.Collections. Its generally a good practice, and it gives NHibernate the maximum flexibility in
  creating the collections for you

  The Database
  Now let’s take a look at the database. The first table is Department, which simply stores department IDs and names. Next, we would
  need to make a table for Student and another for Professor. However, if we look carefully, Professors and Students are almost identical
  (which stands to reason, since they are both human beings). They have first and last names, and some kind of string identifier (title for
  professors, ssn for students). Instead of having two tables, then, we’ll create one table called People. It will have a unique ID per
  person, their first and last names, an identifier field, and a field called PersonType which we will use to distinguish between students
  and professors. Finally, we need a table for our classes (UniversityClass). It has a unique ID, all the descriptive information about the
  class, and two foreign keys: PersonID (which maps to the Professor who teaches the class) and DeptID (which matches the department
  the class belongs to).




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                             15/10/2004
TheServerSide.NET - Print Friendly                                                                                            Página 5 de 13




  The other two tables are join tables, modeling the many-to-many relationships between Students and Classes, and between
  Departments and Professors. These join tables simple match IDs from the appropriate base tables, forming a union between them.

  The Mapping Files
  The next step is to provide the mapping files that fill our domain model from the data tables. Each class requires its own mapping file,
  which can be stored wherever you like. I keep mine mixed in with the class files themselves so that they are easy to find when I make
  changes to the model. Regardless, you’ll need one mapping file per persistent class in your application.

  The mapping files connect your classes and their persistent properties to the database. Your classes can have properties that aren’t
  persistent; this is one of the beautiful things about a transparent data layer. If your domain calls for runtime-calculated properties,
  your classes can have them mixed in with the persistent ones. Your mapping files can just ignore the non-persistent ones.

  Let’s start building the mapping file for Department. All mapping files are genuine XML files, so they start with the standard
  declaration:

  <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?>


  Next, we’ll need to declare that this file is a mapping file for NHibernate. The root element of an NHibernate mapping file looks like
  this:

  <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;>

  </hibernate-mapping>


  That’s the boilerplate part. Now, let’s start constructing the actual mappings. First, we need to tell NHibernate which class type we are
  mapping, using the <class> element. When we pass the class type to NHibernate, we must give it the fully qualified name (including all
  namespaces) and the name of the assembly containing the type. For our Department class, the fully qualified name is




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                              15/10/2004
TheServerSide.NET - Print Friendly                                                                                                 Página 6 de 13


  “nhRegistration.Department ” and the assembly is “nhRegistration”. We also need to feed the table name that holds
  our class data; in this case, “department”.

  <class name=quot;nhRegistration.Department, nhRegistrationquot;
    table=quot;departmentquot;>

  </class>


  We’re doing well. All we have left to do is map the persistent data fields to our schema.
  All property mappings share some common features: the name of the field on the class, the column in the table that contains that
  field’s data, and the type of the field being persisted. Regardless of anything else you will see for different kinds of fields, all three of
  those attributes will be present.

  Let’s look at a standard property: the Department’s Name field. The field itself is declared as a string, and the data table
  defines it as a char field of length 50. The property declaration is very straightforward:

  <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/>


  Any standard properties of a class will look largely the same. Note that the length declaration at the end of the type is no longer needed
  and is being deprecated as NHibernate will reflectively handle the configuration now. In fact, as of the latest release, you can even drop
  the type attribute altogether, and NHibernate will just examine the type of the mapped property.

  A more interesting case is the Department’s “Id” field. Every class has to have a field on it containing data that uniquely identifies
  the instance on the persistence table. For our model, every class has this “Id” field which serves that purpose, though we could have
  used any field with a unique data value. This special field is known as the Id Property. When you map it, you have to provide the
  standard set of attributes, and two special ones: the generator and the unsaved-value.

  The generator of the Id field lets NHibernate know how these unique identifiers will be created: by the programmer, by
  NHibernate, or by the underlying persistence store. Different applications will have different rules about identifiers, and different
  databases offer unique services for managing those values, so you have to pick carefully based on your requirements and
  infrastructure. Common values for generator are:

      l   Identity: the identity column type in Microsoft SQL Server, MySQL, and others
      l   Sequence: sequence tables in DB2, Oracle and others
      l   Hilo: uses a hi/lo algorithm to generate identity values
      l   Native: chooses whichever of the first three values is supported by the underlying database.

  We’ll choose native for ours. The unsaved-value attribute specifies a default value for the Id Property when an object is created
  and not yet persisted. In this case, since we are letting the value of the Id property be created and managed by the database, having a
  default is useful. This is especially true since the default value for this property if not provided will be null, which won’t play nicely with
  the Int32 type of our property. The declaration looks like this:

  <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot; unsaved-value=quot;0quot;>
           <generator class=quot;nativequot; />
  </id>


  Taken all together, our file now looks like this:

  <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?>

  <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;>

       <class name=quot;nhRegistration.Department, nhRegistrationquot;
                     table=quot;departmentquot;>

                            <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot; unsaved-value=quot;0quot;>




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                                  15/10/2004
TheServerSide.NET - Print Friendly                                                                                             Página 7 de 13


                                    <generator class=quot;assignedquot; />
                           </id>
                           <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/>
       </class>
  </hibernate-mapping>


  If we just left it at that, and loaded our database using this mapping file, we’d get a list of Departments whose Name and Id fields
  were populated, but whose Classes and Professors fields were null, since they weren’t mapped in the mapping file. If a field
  isn’t mapped, it is ignored by NHibernate.

  Next up come the collection properties, which have special requirements all their own. Let’s look first at Classes. This is a collection of
  instances of UniversityClass. Remember our requirements for the model: a Department can contain multiple
  UniversityClasses, but a UniversityClass can belong to only one department. This is a one-to-many relationship. To
  model it, we need to use the <set> (or <bag> ) element to show that we are mapping a collection, not a single instance, field.

  <set name=quot;Classesquot;>
     <key column=quot;deptidquot;/>
     <one-to-many class=quot;nhRegistration.UniversityClass,nhRegistrationquot;/>
  </set>


  The “name” attribute of <set> is the field name that will hold the collection, the key column is the name of the column in the
  collected class’s table that maps to the parent class’s Id Property, and the <one-to-many> element determines the type of the
  collected class. Our universityclass table has a field called “deptid” which maps back to the “Id” field in our department table.

  Finally, we have to map the Professors field. Remembering our model, Departments can have many Professors, and
  Professors can belong to more than one Department. This is a many-to-many relationship, and is defined in the database using
  a join table (departmentprofessor) containing the id fields from the two related tables. In order to correctly map this
  relationship, we have to declare the collection mapping much like in the one-to-many example above, but also include the name of the
  join table, and the name of the column that contains the identify field for the related class.

  <set name=quot;Professorsquot; table=quot;departmentprofessorquot;>
           <key column=quot;deptidquot;/>
           <many-to-many class=quot;nhRegistration.Person, nhRegistrationquot;
                    column=quot;personidquot;/>
  </set>


  That’s everything that defines the Department class. The full mapping file reads:

  <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?>
  <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;>
      <class name=quot;nhRegistration.Department, nhRegistrationquot;
                table=quot;departmentquot;>
                    <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot;>
                             <generator class=quot;assignedquot; />
                    </id>
                    <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/>
                    <set name=quot;Classesquot; cascade=quot;allquot;>
                             <key column=quot;deptidquot;/>
                             <one-to-many class=quot;nhRegistration.UniversityClass,
    nhRegistrationquot;/>
                    </set>
                    <set name=quot;Professorsquot; table=quot;departmentprofessorquot;>
                             <key column=quot;deptidquot;/>
                             <many-to-many class=quot;nhRegistration.Person,
                                              nhRegistrationquot; column=quot;personidquot;/>
                    </set>
           </class>




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                              15/10/2004
TheServerSide.NET - Print Friendly                                                                                            Página 8 de 13


  </hibernate-mapping>


  However, if we try to load the project using just this mapping file, it will fail. NHibernate will throw an exception because of the one-
  to-many and many-to-many relationships. When you map a relationship like that, NHibernate expects that both sides of the
  relationships are persistent types; as of right now, we haven’t mapped the UniversityClass or Professor types that exist on
  the other end of those relationships. To successfully load a Department, we have to map those types as well.

  Here’s the mapping file for UniversityClass.

  <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?>
  <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;>

              <class name=quot;nhRegistration.UniversityClass, nhRegistrationquot;
              table=quot;universityclassquot;>
                       <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot;>
                                <generator class=quot;assignedquot; />
                       </id>
                       <property name=quot;Namequot; column=quot;classnamequot;
                                 type=quot;String(50)quot;/>
                       <many-to-one name=quot;Deptquot;
                                class=quot;nhRegistration.Department,nhRegistrationquot;
                                         column=quot;deptidquot;/>

           </class>
  </hibernate-mapping>


  The only new element in this file is the <many-to-one> element that represents the other side of the <one-to-many> element in
  Department.hbm.xml.

  Finally, there’s the Professor class. This one has all kinds of fun. This class is special because Professor is an implementation of
  the Person interface, and shares a table with Student. The mapping file isn’t targeted at Professor, therefore, but at Person
  (Person.hbm.xml). The file maps all the implementations of Person. In order to distinguish between Professors and
  Students, you have to tell NHibernate which field (and values of that field) identify the type of entity in that row. You do this with
  the <discriminator> element.

  If you look back at the domain model, the Person interface identifies three data fields: Id , FirstName and LastName . Both
  Professor and Student expose these fields, but then they begin to differ. Professor has a field called “Identifier” while
  Student has “SSN”. Professors have collections of Departments and UniversityClasses, while Students only
  have a collection of Classes. You can map the common fields in the Person class definition, but the fields that are specific to the
  subtypes must be mapped inside special <subclass> elements.


  (In order to save space, I’ll elide the different collections from this mapping file to highlight the polymorphism-related features. The
  collections look just like the others given in the examples above.)

  <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?>
  <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;>
      <class name=quot;nhRegistration.Person, nhRegistrationquot; table=quot;peoplequot;>
                    <id name=quot;Idquot; column=quot;personidquot; type=quot;Int32quot;>
                             <generator class=quot;assignedquot; />
                    </id>
                    <discriminator column=quot;persontypequot; type=quot;Stringquot;/>
                    <property name=quot;FirstNamequot; column=quot;firstnamequot;
                             type=quot;String(50)quot;/>
                    <property name=quot;LastNamequot; column=quot;lastnamequot;
                             type=quot;String(50)quot;/>
                    <subclass name=quot;nhRegistration.Professor, nhRegistrationquot;
                             discriminator-value=quot;professorquot;>




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                             15/10/2004
TheServerSide.NET - Print Friendly                                                                                         Página 9 de 13


                                   <property name=quot;Identifierquot; column=quot;identifierquot;
                                            type=quot;Stringquot;/>
                          </subclass>
                          <subclass name=quot;nhRegistration.Student, nhRegistrationquot;
                                   discriminator-value=quot;studentquot;>
                                   <property name=quot;SSNquot; column=quot;identifierquot;
                                   type=quot;Stringquot;/>
                          </subclass>
           </class>
  </hibernate-mapping>


  That is finally everything. This set of mapping files can now be used to create, save and load instances in your domain model.

  NHibernate Configuration, SessionFactories and Sessions
  In order to manipulate your persistent objects, you will have to complete the configuration process. This means telling NHibernate
  which mapping files to load. You can do this by pointing NHibernate to the physical files, but this means keeping track of the paths to
  the files no matter where or how your application is installed. Instead, you can let NHibernate find the files as embedded resources in
  your assembly. To do that, you must first set the “Build Action” of each of the mapping files to “Embedded Content”, meaning the
  compiler will add them to the assembly image. Then, you can simply tell NHibernate which classes in your application are the
  persistent classes, and NHibernate will use the class names to find the embedded mapping files that match them.

  Configuration config = new Configuration();
  config.AddClass(typeof(nhRegistration.Department));
  config.AddClass(typeof(nhRegistration.Person));
  config.AddClass(typeof(nhRegistration.UniversityClass));


  You actually manage your persistent classes through a Session object. NHibernate provides a SessionFactory which builds the
  individual Sessions. A Session models a sequence of related persistence methods. As in any database management scenario,
  performance is tied almost directly to the number of roundtrips from your application to the physical database. If every individual
  persistent action required a roundtrip, you would be drastically decreasing the overall speed of your application. Conversely, if you
  simply open a Session and use it for the entire length of your application’s lifetime, you are holding open a valuable and rare
  resource: the physical database connection (though strictly speaking, it is possible to disconnect an open session from a physical
  database connection and still retain state, for now, we’ll operate under the more simplistic Session==Connection assumption).
  Managing your Sessions therefore is one of the most important parts of a good NHibernate application. The best strategy for managing
  your Sessions, and managing persistence logic in general, is to create a generic façade behind which you can plug whatever persistence
  logic you need. This allows you to write your application code against the generic interface and swap implementations out behind the
  scenes (say, if you switched from NHibernate to IBATIS.NET or Microsoft’ ObjectSpaces). The manager object also allows you to finely
  tune your Session management strategy.

  Here’s a partial list of the DBMgr interface for the nhRegistration application:

  public interface DBMgr
  {
           IList getDepartments();
           Department getDepartment(int id);
           void saveDepartment(Department dept);

              IList getClasses();
              //etc...
  }


  The NHibernate implementation of this interface needs to configure the framework and manage our SessionFactory and
  Sessions.

  public class RegMgr : DBMgr
  {
           Configuration config;




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                          15/10/2004
TheServerSide.NET - Print Friendly                                                                                          Página 10 de 13


              ISessionFactory factory;

              public RegMgr()
              {
                       config = new Configuration();
                       config.AddClass(typeof(nhRegistration.Department));
                       config.AddClass(typeof(nhRegistration.Person));
                       config.AddClass(typeof(nhRegistration.UniversityClass));

                           factory = config.BuildSessionFactory();

              }


  From then on, the other persistent methods (that implement those found on DBMgr ) can make use of the stored SessionFactory
  to open and use individual Sessions.


  Creating, Loading and Saving Objects
  Since the purpose of a Session is to provide a mechanism for managing the performance of your application, and the nature of that
  management is preventing unnecessary round trips to the database, it stands to reason that operations on a Session do not always
  result in direct operations against the underlying database. In fact, it is the point of the Session to cache operations until they can be
  batched to the database, thus saving round trips. All of which means that when you call a persistent method on a Session , it may or
  may not result in immediate changes to the database.

  Usually, changes are only written to the database when the Session’s flush() method is called. You can do this directly, of
  course, but it is more common to find that flush() is being called on your behalf during some other operation, namely a
  transactional commit.

  Let’s be frank: if you are building a database application, but aren’t concerned with transactions, you should probably take a few
  minutes to re-evaluate your design. It is vital, even when you are coding your SQL queries by hand, to make sure that atomic units of
  change to the database get executed transactionally. This becomes exponentially more important when using an O/R mapping layer
  like NHibernate, because a simple statement like save(dept) can have cascading effects on the database (changes to professors, or
  classes, or join tables, etc.). If any one of those cascading changes fails, and you aren’t using transactions to manage your writes, then
  you will be leaving your database in an unusable state. So, when using NHibernate, don’t use Sessions without Transactions.

  The common usage pattern is this:

              ISession session;
              ITransaction tx;

              try
              {
                           session = factory.OpenSession();
                           tx = session.BeginTransaction();
                           // do database work
                           tx.Commit();
                           session.Close();
              }
              catch (Exception ex)
              {
                       tx.Rollback();
                       session.Close();
                       // further exception handling
              }


  The authors of the Hibernate documentation strenuously suggest never treating an exception as recoverable, hence rolling back the
  transaction as the first operation in your exception handling code. This is largely because NHibernate manages cascading updates
  depending on the relationships between your objects, and failures might represent failures anywhere along that chain. The best idea is




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                             15/10/2004
TheServerSide.NET - Print Friendly                                                                                            Página 11 de 13


  to just roll back everything, fix the problem in the domain model, and try again.

  Let’s talk a look at the most common types of activities for our persistent objects. We’ll examine the implementation of the first three
  methods of the DBMgr interface shown above. First up, getDepartments(). This method returns a list of all the departments in
  the university.

  public IList getDepartments()
  {
           IList depts = null;
           try
           {
                    ISession session = factory.OpenSession();
                    ITransaction tx = session.BeginTransaction();
                    depts = session.CreateCriteria(typeof(Department)).List();
                    session.Close();
           }
           catch (Exception ex)
           {
                    tx.Rollback();
                    session.Close();
                    // handle exception.
           }
           return depts;
  }


  The Session object exposes the CreateCriteria() method, which takes a persistent class Type as its only argument. This tells
  NHibernate to gear up to interact with the tables mapped to this object; asking for the List() property of the results returns all the
  instances of that criteria. In this case, we’ll get back a List containing instances of Department, fully populated from the database
  (including all the other persistent objects related to Department). This straightforward method is used to iterate through all
  instances of a class in your database.

  If you want to retrieve a specific instance from the database, you have to know the specific value of the identifier field for the target
  class that you are looking for.

  public Department getDepartment(int i)
  {
           Department d = null;
           try
           {
                ISession session = factory.OpenSession();
                ITransaction tx = session.BeginTransaction();
                d = (Department)session.Load(typeof(nhRegistration.Department), i);
                session.Close();
           }
           catch (Exception ex)
           {
                    tx.Rollback();
                    session.Close();
                    // handle exception.       }
           return d;
  }


  Just remember to cast the results of session.Load() to the appropriate type, as what you get back is an Object.

  Finally, what if you want to save changes to an instance (or create a new instance)? Session provides two methods:
  Session.Save() for creating a new instance, and Session.Update() for modifying an existing instance. You have to keep the two
  separate; Session conflicts and database errors occur if you try to use the wrong method. In our interface, though, our DBMgr




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                               15/10/2004
TheServerSide.NET - Print Friendly                                                                                          Página 12 de 13


  implementation only has one method, saveDepartment(Department dept). It doesn’t make much sense for such a simple
  application to force developers to distinguish between persisting a new object versus an existing one, so the interface only exposes that
  single entry point.

  In our implementation, however, we are still required to make that distinction. Here is a (altogether too simple) version:

  public void saveDepartment(Department dept)
  {
           try
           {
                    ISession session = factory.OpenSession();
                    ITransaction tx = session.BeginTransaction();

                           if(dept.Id == 0)
                           {
                                    session.Save(dept);
                           }
                           else
                           {
                                    session.Update(dept);
                           }
                           tx.Commit();
                           session.Close();
              }
              catch (Exception ex)
              {
                       tx.Rollback();
                       session.Close();
                       // handle exception
              }
  }


  First, before we persist the instance, we determine if it is a new instance or modified pre-existing version. With a simple integer-based
  identification field, we can just check to see if it has a value of 0, which means it has no corresponding row in our database (remember
  our unsaved-value attribute above). You can imagine, though, that this logic breaks down in the face of more complicated
  identification fields. Once we make that determination, we invoke the correct method on Session to do the work for us.

  Other Concerns
  This article has been a whirlwind tour of NHibernate, giving you just the basics you’ll need to get started. Clearly, there is much I have
  left out, glossed over or hidden behind a veil of fog. In my next article, we’ll tackle some of those issues, like:

      l   Parameterized queries in HQL (Hibernate Query Language)
      l   Caching
      l   Advanced collection semantics (lazy loading, bidirectional mapping)
      l   Advanced session management (disconnected objects, SaveOrUpdate semantics)
      l   Limiting configuration steps (only building the SessionFactory once)

  …and more. I hope this article has piqued your interest in the power of O/R mappers. Remember, NHibernate is just one of many, and
  if this looks interesting but not QUITE to your liking, there’s many more out there to choose from.

  Authors

          Justin Gehtland is a founding member of Relevance, LLC, a consultant group dedicated to elevating the practice of software
          development. He is the co-author of Windows Forms Programming in Visual Basic .NET (Addison Wesley, 2003) and
          Effective Visual Basic (Addison Wesley, 2001). Justin is an industry speaker, and instructor with DevelopMentor in the .NET
          curriculum.




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                             15/10/2004
TheServerSide.NET - Print Friendly                                                                                   Página 13 de 13



                            News | Discussions | Tech talks | Case studies | Articles | Media kit | Signup | About
                                         All Content Copyright ©2004 TheServerSide Privacy Policy




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate                                                    15/10/2004

Contenu connexe

Tendances

9. Object Relational Databases in DBMS
9. Object Relational Databases in DBMS9. Object Relational Databases in DBMS
9. Object Relational Databases in DBMS
koolkampus
 
Applying Semantic Web Technologies to Services of e-learning System
Applying Semantic Web Technologies to Services of e-learning SystemApplying Semantic Web Technologies to Services of e-learning System
Applying Semantic Web Technologies to Services of e-learning System
International Journal of Engineering Inventions www.ijeijournal.com
 
Mobile Email Security
Mobile Email SecurityMobile Email Security
Mobile Email Security
Rahul Sihag
 
Sql and mysql database concepts
Sql and mysql database conceptsSql and mysql database concepts
Sql and mysql database concepts
Selamawit Feleke
 

Tendances (20)

Ordbms
OrdbmsOrdbms
Ordbms
 
Object-Relational Database Systems(ORDBMSs)
Object-Relational Database Systems(ORDBMSs)Object-Relational Database Systems(ORDBMSs)
Object-Relational Database Systems(ORDBMSs)
 
Oodbms ch 20
Oodbms ch 20Oodbms ch 20
Oodbms ch 20
 
Semantic Web Nature
Semantic Web NatureSemantic Web Nature
Semantic Web Nature
 
Object Oriented Database Management System
Object Oriented Database Management SystemObject Oriented Database Management System
Object Oriented Database Management System
 
9. Object Relational Databases in DBMS
9. Object Relational Databases in DBMS9. Object Relational Databases in DBMS
9. Object Relational Databases in DBMS
 
D B M S Animate
D B M S AnimateD B M S Animate
D B M S Animate
 
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASESSCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
 
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASESSCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
SCHEMA BASED STORAGE OF XML DOCUMENTS IN RELATIONAL DATABASES
 
Applying Semantic Web Technologies to Services of e-learning System
Applying Semantic Web Technologies to Services of e-learning SystemApplying Semantic Web Technologies to Services of e-learning System
Applying Semantic Web Technologies to Services of e-learning System
 
DBMS FOR STUDENTS MUST DOWNLOAD AND READ
DBMS FOR STUDENTS MUST DOWNLOAD AND READDBMS FOR STUDENTS MUST DOWNLOAD AND READ
DBMS FOR STUDENTS MUST DOWNLOAD AND READ
 
Oracle sql in 7 days by suesh.n v 1.0
Oracle sql in 7 days by suesh.n v 1.0Oracle sql in 7 days by suesh.n v 1.0
Oracle sql in 7 days by suesh.n v 1.0
 
Database Management System
Database Management SystemDatabase Management System
Database Management System
 
Oracle
OracleOracle
Oracle
 
Rdbms concepts
Rdbms conceptsRdbms concepts
Rdbms concepts
 
PPL, OQL & oodbms
PPL, OQL & oodbmsPPL, OQL & oodbms
PPL, OQL & oodbms
 
12 SQL
12 SQL12 SQL
12 SQL
 
Mobile Email Security
Mobile Email SecurityMobile Email Security
Mobile Email Security
 
Sql and mysql database concepts
Sql and mysql database conceptsSql and mysql database concepts
Sql and mysql database concepts
 
Unit 02 dbms
Unit 02 dbmsUnit 02 dbms
Unit 02 dbms
 

En vedette

Nhibernate Part 2
Nhibernate   Part 2Nhibernate   Part 2
Nhibernate Part 2
guest075fec
 
nHibernate Caching
nHibernate CachingnHibernate Caching
nHibernate Caching
Guo Albert
 
Introduction to NHibernate
Introduction to NHibernateIntroduction to NHibernate
Introduction to NHibernate
Dublin Alt,Net
 
NHibernate for .NET
NHibernate for .NETNHibernate for .NET
NHibernate for .NET
Guo Albert
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
Samnang Chhun
 

En vedette (20)

Hibernate
HibernateHibernate
Hibernate
 
NHibernate from inside
NHibernate from insideNHibernate from inside
NHibernate from inside
 
Entity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks ComparedEntity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks Compared
 
NHibernate - SQLBits IV
NHibernate - SQLBits IVNHibernate - SQLBits IV
NHibernate - SQLBits IV
 
OpenERP 6.0
OpenERP 6.0OpenERP 6.0
OpenERP 6.0
 
NHibernate
NHibernateNHibernate
NHibernate
 
Ddd
DddDdd
Ddd
 
NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)
 
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca..."ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
 
Nhibernate Part 2
Nhibernate   Part 2Nhibernate   Part 2
Nhibernate Part 2
 
nHibernate Caching
nHibernate CachingnHibernate Caching
nHibernate Caching
 
Introduction to NHibernate
Introduction to NHibernateIntroduction to NHibernate
Introduction to NHibernate
 
NHibernate
NHibernateNHibernate
NHibernate
 
NHibernate
NHibernateNHibernate
NHibernate
 
NHibernate for .NET
NHibernate for .NETNHibernate for .NET
NHibernate for .NET
 
ASP.Net MVC
ASP.Net MVCASP.Net MVC
ASP.Net MVC
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
 
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETMicro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
 
Руйнуємо .NET Міфи
Руйнуємо .NET МіфиРуйнуємо .NET Міфи
Руйнуємо .NET Міфи
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated
 

Similaire à Nhibernate Part 1

Document Based Data Modeling Technique
Document Based Data Modeling TechniqueDocument Based Data Modeling Technique
Document Based Data Modeling Technique
Carmen Sanborn
 
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
Karen Thompson
 
Improved Presentation and Facade Layer Operations for Software Engineering Pr...
Improved Presentation and Facade Layer Operations for Software Engineering Pr...Improved Presentation and Facade Layer Operations for Software Engineering Pr...
Improved Presentation and Facade Layer Operations for Software Engineering Pr...
Dr. Amarjeet Singh
 

Similaire à Nhibernate Part 1 (20)

Document Based Data Modeling Technique
Document Based Data Modeling TechniqueDocument Based Data Modeling Technique
Document Based Data Modeling Technique
 
PATTERNS07 - Data Representation in C#
PATTERNS07 - Data Representation in C#PATTERNS07 - Data Representation in C#
PATTERNS07 - Data Representation in C#
 
Data Base
Data BaseData Base
Data Base
 
MADHU.pptx
MADHU.pptxMADHU.pptx
MADHU.pptx
 
Asp.net interview questions
Asp.net interview questionsAsp.net interview questions
Asp.net interview questions
 
Bp301
Bp301Bp301
Bp301
 
Using In-Memory Encrypted Databases on the Cloud
Using In-Memory Encrypted Databases on the CloudUsing In-Memory Encrypted Databases on the Cloud
Using In-Memory Encrypted Databases on the Cloud
 
Presentazione pagano1
Presentazione pagano1Presentazione pagano1
Presentazione pagano1
 
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
Cis 555 Week 4 Assignment 2 Automated Teller Machine (Atm)...
 
Hibernate I
Hibernate IHibernate I
Hibernate I
 
Building nTier Applications with Entity Framework Services (Part 1)
Building nTier Applications with Entity Framework Services (Part 1)Building nTier Applications with Entity Framework Services (Part 1)
Building nTier Applications with Entity Framework Services (Part 1)
 
What Is Super Key In Dbms
What Is Super Key In DbmsWhat Is Super Key In Dbms
What Is Super Key In Dbms
 
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
 
2012 the clean architecture by Uncle bob
2012 the clean architecture by Uncle bob 2012 the clean architecture by Uncle bob
2012 the clean architecture by Uncle bob
 
Hibernate training at HarshithaTechnologySolutions @ Nizampet
Hibernate training at HarshithaTechnologySolutions @ NizampetHibernate training at HarshithaTechnologySolutions @ Nizampet
Hibernate training at HarshithaTechnologySolutions @ Nizampet
 
Overview of entity framework by software outsourcing company india
Overview of entity framework by software outsourcing company indiaOverview of entity framework by software outsourcing company india
Overview of entity framework by software outsourcing company india
 
Queues, Pools and Caches paper
Queues, Pools and Caches paperQueues, Pools and Caches paper
Queues, Pools and Caches paper
 
Queues, Pools and Caches - Paper
Queues, Pools and Caches - PaperQueues, Pools and Caches - Paper
Queues, Pools and Caches - Paper
 
A Whirlwind Tour of Spatial Joins
A Whirlwind Tour of Spatial JoinsA Whirlwind Tour of Spatial Joins
A Whirlwind Tour of Spatial Joins
 
Improved Presentation and Facade Layer Operations for Software Engineering Pr...
Improved Presentation and Facade Layer Operations for Software Engineering Pr...Improved Presentation and Facade Layer Operations for Software Engineering Pr...
Improved Presentation and Facade Layer Operations for Software Engineering Pr...
 

Dernier

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 

Dernier (20)

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

Nhibernate Part 1

  • 1. TheServerSide.NET - Print Friendly Página 1 de 13 NHibernate Discuss Printer friendly August 12, 2004 Chances are, as a .NET developer, you are already intimately familiar with the ADO.NET dataset. If you are an “enterprise” developer, those odds approach 100%. Database interaction via the FCL centers around retrieving a static snapshot of some portion of the database and manipulating it via the dataset, which mimics the RDBMS in almost every way: the data is tabular, relationships between data are modeled by foreign keys, data is largely untyped. Since the dataset provides a static, in-memory cache of data, it makes the manipulation of that data much more efficient than requiring constant round trips to the live data store. The problem with the dataset is that it doesn’t fit particularly well with modern object-oriented application design. Whereas datasets have tabular data, we tend to code using objects. Datasets have foreign key relationships, our domain objects use references. Where we want to use only methods, datasets require a certain amount of SQL code. Of course, some of these problems can be solved through the use of “strongly typed” datasets, but the fact remains that you are changing modes as you move from your domain model to your data access and back again. Depending on how you choose to layer that data access code into the application, changes to the data store can have enormous ripple-effects on your codebase. Last month, Bruce Tate and I released a new book called “Better, Faster, Lighter Java”. Don’t let that “j” word in the title throw you too much; the principles we espouse in the book are equally applicable to any modern development platform. One of those principles is transparency; the key to any enterprise application is the domain model. These are the classes that model, and solve, your customers’ business problems. If you customer is a bank, your domain model is filled with Accounts, Deposits and Loans. If your customer is a travel agent, your domain is filled with Tours and Hotels and Airlines. It is in these classes that your customers’ problems are addressed; everything else is just a service to support the domain. I mean things like data storage, message transport, transactional control, etc. As much as possible, you want those services to be transparent to your domain model. Transparency means that your model benefits from those services without being modified by them. It shouldn’t require special code in your domain to utilize those services, it shouldn’t require specific containers, or interfaces to implement. Which means that your domain architecture can be 100% focused on the business problem at hand, not technical problems outside the business. A side effect of achieving transparency is that you can replace services with alternate providers or add new services without changing your domain. Coding directly against the dataset breaks the transparency. It is obvious inside of your code what storage mechanism you use, and it affects the way your code is written. Another approach to storage is the use of an object-relational mapping tool. Microsoft is in the process of building such a framework, called ObjectSpaces, but recently announced it would be delayed until as far as 2006. NHibernate, an open source solution, is available today and solves the same set of problems. With NHibernate, your code and your data schema remain decoupled, and the only visible indicator of the existence of the O/R layer are the mapping files. With HNibernate, you’ll see that these consist of configuration settings for the O/R framework itself (connecting to a data source, identifying the data language, etc.) and mapping your domain objects to the data tables. There are a variety of other O/R frameworks available today, some commercial and some open source. For the purposes of this article, though, we’ll focus on NHibernate. It has a lot of momentum carrying over from the Java side of the world, and is extremely easy to get started with. However, if the general techniques we see in this article appeal to you, I suggest you take a look at the other options available to see if others are a better fit for your needs. To get started, you’ll need to download the framework at http://nhibernate.sourceforge.net. Reference the assembly in your project. The next step will be to add the appropriate configuration settings to your application’s config file to tell NHibernate where and what your data store is. For the purposes of this article, we’ll use Microsoft SQL Server, though you could just as easily target Oracle, MySQL, or any number of other vendors. To map to a SQL Server instance, here is what your configuration settings might look like: http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 2. TheServerSide.NET - Print Friendly Página 2 de 13 <configuration> <configSections> <section name=quot;nhibernatequot; type=quot;System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089quot; /> </configSections> <nhibernate> <add key=quot;hibernate.connection.providerquot; value=quot;NHibernate.Connection.DriverConnectionProviderquot; /> <add key=quot;hibernate.dialectquot; value=quot;NHibernate.Dialect.MsSql2000Dialectquot; /> <add key=quot;hibernate.connection.driver_classquot; value=quot;NHibernate.Driver.SqlClientDriverquot; /> <add key=quot;hibernate.connection.connection_stringquot; value=quot;Server=localhost;initial catalog=nhibernate;User ID=someuser;Password=somepwd;Min Pool Size=2quot; /> </nhibernate> </configuration> Once you have configured the framework to recognize your data store, the next step is to create your domain model and database representation. It is entirely plausible to do those steps in either order – if your application is depending on a highly efficient storage schema, perhaps starting there is appropriate. However, if the database is just a place to store object state, then it probably makes more sense to start in the domain classes. There is a third option – start with the mapping files that will describe the relationships between your classes and tables. NHibernate provides a tool today that can auto-generate DDL from your mapping files. A recent addition to the project is a NAnt task that will auto-generate C# stubs from the mapping files. Taken together, you can adequately construct a base implementation by just coding up the mappings and letting NHibernate’s tools take care of the rest. NHibernate provides a tool today that can auto-generate DDL from your mapping files. A recent addition to the project is a NAnt task that will auto-generate C# stubs from the mapping files. Taken together, you can adequately construct a base implementation by just coding up the mappings and letting NHibernate’s tools take care of the rest. The Domain Model We’ll start with the domain model. For this article, we’ll tackle just a narrow segment of a larger enterprise application. Specifically, we’ll look at part of a university registration system. For our purposes, we’ll examine the following classes: 1. Department: describes one segment of the University’s curriculum. 2. UniversityClass: one class offered at the school (the funky name is to prevent using a reserved word as the name of the class). 3. Professor: person who teaches a class. 4. Student: person who takes a class. Each of these classes has its own data fields, but the relationships between them are where the fun starts. http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 3. TheServerSide.NET - Print Friendly Página 3 de 13 A department can contain zero, one or more professors. A professor can be associated with more than one department. A department contains one or more classes. A class belongs to only one department. A class is taught by a single professor, but a professor can teach multiple classes. Many students can take a single class, and students (should) take more than one class. There is no direct relationship between students and departments or professors (any relationship between student and professor is probably illegal, anyway). Our domain objects are fairly straightforward. Here’s the list of classes and their data fields: public class Department { private int id; private string name; private IDictionary classes; private IDictionary professors; } public class Professor : Person { private int id; private string firstname; private string lastname; private string id; private IDictionary departments; private IDictionary classes; } public class UniversityClass { private int id; private string name; private string number; private string syllabus; private DateTime startDate; private Professor professor; private IDictionary students; private Department department; } public class Student : Person http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 4. TheServerSide.NET - Print Friendly Página 4 de 13 { private int id; private string firstname; private string lastname; private string ssn; private IDictionary classes; } public interface Person { public int Id; public string FirstName; public string LastName; } Of course, you’ll probably want to provide public properties to wrap those fields, as it is good coding practice. Though NHibernate can work directly with private and protected fields, it just generally makes more sense to use properties for field access. Secondly, remember that our Professor and Student classes will share a table. In the domain, they share several data fields as well (FirstName, LastName and ID). In our domain model, we represent this relationship through some form of inheritance. In this case, they both implement the Person interface, as shown. Finally, you will see that our collection fields are all defined using IDictionary. When defining your collections in your domain, stick to the interfaces provided for you in System.Collections. Its generally a good practice, and it gives NHibernate the maximum flexibility in creating the collections for you The Database Now let’s take a look at the database. The first table is Department, which simply stores department IDs and names. Next, we would need to make a table for Student and another for Professor. However, if we look carefully, Professors and Students are almost identical (which stands to reason, since they are both human beings). They have first and last names, and some kind of string identifier (title for professors, ssn for students). Instead of having two tables, then, we’ll create one table called People. It will have a unique ID per person, their first and last names, an identifier field, and a field called PersonType which we will use to distinguish between students and professors. Finally, we need a table for our classes (UniversityClass). It has a unique ID, all the descriptive information about the class, and two foreign keys: PersonID (which maps to the Professor who teaches the class) and DeptID (which matches the department the class belongs to). http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 5. TheServerSide.NET - Print Friendly Página 5 de 13 The other two tables are join tables, modeling the many-to-many relationships between Students and Classes, and between Departments and Professors. These join tables simple match IDs from the appropriate base tables, forming a union between them. The Mapping Files The next step is to provide the mapping files that fill our domain model from the data tables. Each class requires its own mapping file, which can be stored wherever you like. I keep mine mixed in with the class files themselves so that they are easy to find when I make changes to the model. Regardless, you’ll need one mapping file per persistent class in your application. The mapping files connect your classes and their persistent properties to the database. Your classes can have properties that aren’t persistent; this is one of the beautiful things about a transparent data layer. If your domain calls for runtime-calculated properties, your classes can have them mixed in with the persistent ones. Your mapping files can just ignore the non-persistent ones. Let’s start building the mapping file for Department. All mapping files are genuine XML files, so they start with the standard declaration: <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?> Next, we’ll need to declare that this file is a mapping file for NHibernate. The root element of an NHibernate mapping file looks like this: <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;> </hibernate-mapping> That’s the boilerplate part. Now, let’s start constructing the actual mappings. First, we need to tell NHibernate which class type we are mapping, using the <class> element. When we pass the class type to NHibernate, we must give it the fully qualified name (including all namespaces) and the name of the assembly containing the type. For our Department class, the fully qualified name is http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 6. TheServerSide.NET - Print Friendly Página 6 de 13 “nhRegistration.Department ” and the assembly is “nhRegistration”. We also need to feed the table name that holds our class data; in this case, “department”. <class name=quot;nhRegistration.Department, nhRegistrationquot; table=quot;departmentquot;> </class> We’re doing well. All we have left to do is map the persistent data fields to our schema. All property mappings share some common features: the name of the field on the class, the column in the table that contains that field’s data, and the type of the field being persisted. Regardless of anything else you will see for different kinds of fields, all three of those attributes will be present. Let’s look at a standard property: the Department’s Name field. The field itself is declared as a string, and the data table defines it as a char field of length 50. The property declaration is very straightforward: <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/> Any standard properties of a class will look largely the same. Note that the length declaration at the end of the type is no longer needed and is being deprecated as NHibernate will reflectively handle the configuration now. In fact, as of the latest release, you can even drop the type attribute altogether, and NHibernate will just examine the type of the mapped property. A more interesting case is the Department’s “Id” field. Every class has to have a field on it containing data that uniquely identifies the instance on the persistence table. For our model, every class has this “Id” field which serves that purpose, though we could have used any field with a unique data value. This special field is known as the Id Property. When you map it, you have to provide the standard set of attributes, and two special ones: the generator and the unsaved-value. The generator of the Id field lets NHibernate know how these unique identifiers will be created: by the programmer, by NHibernate, or by the underlying persistence store. Different applications will have different rules about identifiers, and different databases offer unique services for managing those values, so you have to pick carefully based on your requirements and infrastructure. Common values for generator are: l Identity: the identity column type in Microsoft SQL Server, MySQL, and others l Sequence: sequence tables in DB2, Oracle and others l Hilo: uses a hi/lo algorithm to generate identity values l Native: chooses whichever of the first three values is supported by the underlying database. We’ll choose native for ours. The unsaved-value attribute specifies a default value for the Id Property when an object is created and not yet persisted. In this case, since we are letting the value of the Id property be created and managed by the database, having a default is useful. This is especially true since the default value for this property if not provided will be null, which won’t play nicely with the Int32 type of our property. The declaration looks like this: <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot; unsaved-value=quot;0quot;> <generator class=quot;nativequot; /> </id> Taken all together, our file now looks like this: <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?> <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;> <class name=quot;nhRegistration.Department, nhRegistrationquot; table=quot;departmentquot;> <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot; unsaved-value=quot;0quot;> http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 7. TheServerSide.NET - Print Friendly Página 7 de 13 <generator class=quot;assignedquot; /> </id> <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/> </class> </hibernate-mapping> If we just left it at that, and loaded our database using this mapping file, we’d get a list of Departments whose Name and Id fields were populated, but whose Classes and Professors fields were null, since they weren’t mapped in the mapping file. If a field isn’t mapped, it is ignored by NHibernate. Next up come the collection properties, which have special requirements all their own. Let’s look first at Classes. This is a collection of instances of UniversityClass. Remember our requirements for the model: a Department can contain multiple UniversityClasses, but a UniversityClass can belong to only one department. This is a one-to-many relationship. To model it, we need to use the <set> (or <bag> ) element to show that we are mapping a collection, not a single instance, field. <set name=quot;Classesquot;> <key column=quot;deptidquot;/> <one-to-many class=quot;nhRegistration.UniversityClass,nhRegistrationquot;/> </set> The “name” attribute of <set> is the field name that will hold the collection, the key column is the name of the column in the collected class’s table that maps to the parent class’s Id Property, and the <one-to-many> element determines the type of the collected class. Our universityclass table has a field called “deptid” which maps back to the “Id” field in our department table. Finally, we have to map the Professors field. Remembering our model, Departments can have many Professors, and Professors can belong to more than one Department. This is a many-to-many relationship, and is defined in the database using a join table (departmentprofessor) containing the id fields from the two related tables. In order to correctly map this relationship, we have to declare the collection mapping much like in the one-to-many example above, but also include the name of the join table, and the name of the column that contains the identify field for the related class. <set name=quot;Professorsquot; table=quot;departmentprofessorquot;> <key column=quot;deptidquot;/> <many-to-many class=quot;nhRegistration.Person, nhRegistrationquot; column=quot;personidquot;/> </set> That’s everything that defines the Department class. The full mapping file reads: <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?> <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;> <class name=quot;nhRegistration.Department, nhRegistrationquot; table=quot;departmentquot;> <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot;> <generator class=quot;assignedquot; /> </id> <property name=quot;Namequot; column=quot;deptnamequot; type=quot;String(50)quot;/> <set name=quot;Classesquot; cascade=quot;allquot;> <key column=quot;deptidquot;/> <one-to-many class=quot;nhRegistration.UniversityClass, nhRegistrationquot;/> </set> <set name=quot;Professorsquot; table=quot;departmentprofessorquot;> <key column=quot;deptidquot;/> <many-to-many class=quot;nhRegistration.Person, nhRegistrationquot; column=quot;personidquot;/> </set> </class> http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 8. TheServerSide.NET - Print Friendly Página 8 de 13 </hibernate-mapping> However, if we try to load the project using just this mapping file, it will fail. NHibernate will throw an exception because of the one- to-many and many-to-many relationships. When you map a relationship like that, NHibernate expects that both sides of the relationships are persistent types; as of right now, we haven’t mapped the UniversityClass or Professor types that exist on the other end of those relationships. To successfully load a Department, we have to map those types as well. Here’s the mapping file for UniversityClass. <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?> <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;> <class name=quot;nhRegistration.UniversityClass, nhRegistrationquot; table=quot;universityclassquot;> <id name=quot;Idquot; column=quot;deptidquot; type=quot;Int32quot;> <generator class=quot;assignedquot; /> </id> <property name=quot;Namequot; column=quot;classnamequot; type=quot;String(50)quot;/> <many-to-one name=quot;Deptquot; class=quot;nhRegistration.Department,nhRegistrationquot; column=quot;deptidquot;/> </class> </hibernate-mapping> The only new element in this file is the <many-to-one> element that represents the other side of the <one-to-many> element in Department.hbm.xml. Finally, there’s the Professor class. This one has all kinds of fun. This class is special because Professor is an implementation of the Person interface, and shares a table with Student. The mapping file isn’t targeted at Professor, therefore, but at Person (Person.hbm.xml). The file maps all the implementations of Person. In order to distinguish between Professors and Students, you have to tell NHibernate which field (and values of that field) identify the type of entity in that row. You do this with the <discriminator> element. If you look back at the domain model, the Person interface identifies three data fields: Id , FirstName and LastName . Both Professor and Student expose these fields, but then they begin to differ. Professor has a field called “Identifier” while Student has “SSN”. Professors have collections of Departments and UniversityClasses, while Students only have a collection of Classes. You can map the common fields in the Person class definition, but the fields that are specific to the subtypes must be mapped inside special <subclass> elements. (In order to save space, I’ll elide the different collections from this mapping file to highlight the polymorphism-related features. The collections look just like the others given in the examples above.) <?xml version=quot;1.0quot; encoding=quot;utf-8quot; ?> <hibernate-mapping xmlns=quot;urn:nhibernate-mapping-2.0quot;> <class name=quot;nhRegistration.Person, nhRegistrationquot; table=quot;peoplequot;> <id name=quot;Idquot; column=quot;personidquot; type=quot;Int32quot;> <generator class=quot;assignedquot; /> </id> <discriminator column=quot;persontypequot; type=quot;Stringquot;/> <property name=quot;FirstNamequot; column=quot;firstnamequot; type=quot;String(50)quot;/> <property name=quot;LastNamequot; column=quot;lastnamequot; type=quot;String(50)quot;/> <subclass name=quot;nhRegistration.Professor, nhRegistrationquot; discriminator-value=quot;professorquot;> http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 9. TheServerSide.NET - Print Friendly Página 9 de 13 <property name=quot;Identifierquot; column=quot;identifierquot; type=quot;Stringquot;/> </subclass> <subclass name=quot;nhRegistration.Student, nhRegistrationquot; discriminator-value=quot;studentquot;> <property name=quot;SSNquot; column=quot;identifierquot; type=quot;Stringquot;/> </subclass> </class> </hibernate-mapping> That is finally everything. This set of mapping files can now be used to create, save and load instances in your domain model. NHibernate Configuration, SessionFactories and Sessions In order to manipulate your persistent objects, you will have to complete the configuration process. This means telling NHibernate which mapping files to load. You can do this by pointing NHibernate to the physical files, but this means keeping track of the paths to the files no matter where or how your application is installed. Instead, you can let NHibernate find the files as embedded resources in your assembly. To do that, you must first set the “Build Action” of each of the mapping files to “Embedded Content”, meaning the compiler will add them to the assembly image. Then, you can simply tell NHibernate which classes in your application are the persistent classes, and NHibernate will use the class names to find the embedded mapping files that match them. Configuration config = new Configuration(); config.AddClass(typeof(nhRegistration.Department)); config.AddClass(typeof(nhRegistration.Person)); config.AddClass(typeof(nhRegistration.UniversityClass)); You actually manage your persistent classes through a Session object. NHibernate provides a SessionFactory which builds the individual Sessions. A Session models a sequence of related persistence methods. As in any database management scenario, performance is tied almost directly to the number of roundtrips from your application to the physical database. If every individual persistent action required a roundtrip, you would be drastically decreasing the overall speed of your application. Conversely, if you simply open a Session and use it for the entire length of your application’s lifetime, you are holding open a valuable and rare resource: the physical database connection (though strictly speaking, it is possible to disconnect an open session from a physical database connection and still retain state, for now, we’ll operate under the more simplistic Session==Connection assumption). Managing your Sessions therefore is one of the most important parts of a good NHibernate application. The best strategy for managing your Sessions, and managing persistence logic in general, is to create a generic façade behind which you can plug whatever persistence logic you need. This allows you to write your application code against the generic interface and swap implementations out behind the scenes (say, if you switched from NHibernate to IBATIS.NET or Microsoft’ ObjectSpaces). The manager object also allows you to finely tune your Session management strategy. Here’s a partial list of the DBMgr interface for the nhRegistration application: public interface DBMgr { IList getDepartments(); Department getDepartment(int id); void saveDepartment(Department dept); IList getClasses(); //etc... } The NHibernate implementation of this interface needs to configure the framework and manage our SessionFactory and Sessions. public class RegMgr : DBMgr { Configuration config; http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 10. TheServerSide.NET - Print Friendly Página 10 de 13 ISessionFactory factory; public RegMgr() { config = new Configuration(); config.AddClass(typeof(nhRegistration.Department)); config.AddClass(typeof(nhRegistration.Person)); config.AddClass(typeof(nhRegistration.UniversityClass)); factory = config.BuildSessionFactory(); } From then on, the other persistent methods (that implement those found on DBMgr ) can make use of the stored SessionFactory to open and use individual Sessions. Creating, Loading and Saving Objects Since the purpose of a Session is to provide a mechanism for managing the performance of your application, and the nature of that management is preventing unnecessary round trips to the database, it stands to reason that operations on a Session do not always result in direct operations against the underlying database. In fact, it is the point of the Session to cache operations until they can be batched to the database, thus saving round trips. All of which means that when you call a persistent method on a Session , it may or may not result in immediate changes to the database. Usually, changes are only written to the database when the Session’s flush() method is called. You can do this directly, of course, but it is more common to find that flush() is being called on your behalf during some other operation, namely a transactional commit. Let’s be frank: if you are building a database application, but aren’t concerned with transactions, you should probably take a few minutes to re-evaluate your design. It is vital, even when you are coding your SQL queries by hand, to make sure that atomic units of change to the database get executed transactionally. This becomes exponentially more important when using an O/R mapping layer like NHibernate, because a simple statement like save(dept) can have cascading effects on the database (changes to professors, or classes, or join tables, etc.). If any one of those cascading changes fails, and you aren’t using transactions to manage your writes, then you will be leaving your database in an unusable state. So, when using NHibernate, don’t use Sessions without Transactions. The common usage pattern is this: ISession session; ITransaction tx; try { session = factory.OpenSession(); tx = session.BeginTransaction(); // do database work tx.Commit(); session.Close(); } catch (Exception ex) { tx.Rollback(); session.Close(); // further exception handling } The authors of the Hibernate documentation strenuously suggest never treating an exception as recoverable, hence rolling back the transaction as the first operation in your exception handling code. This is largely because NHibernate manages cascading updates depending on the relationships between your objects, and failures might represent failures anywhere along that chain. The best idea is http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 11. TheServerSide.NET - Print Friendly Página 11 de 13 to just roll back everything, fix the problem in the domain model, and try again. Let’s talk a look at the most common types of activities for our persistent objects. We’ll examine the implementation of the first three methods of the DBMgr interface shown above. First up, getDepartments(). This method returns a list of all the departments in the university. public IList getDepartments() { IList depts = null; try { ISession session = factory.OpenSession(); ITransaction tx = session.BeginTransaction(); depts = session.CreateCriteria(typeof(Department)).List(); session.Close(); } catch (Exception ex) { tx.Rollback(); session.Close(); // handle exception. } return depts; } The Session object exposes the CreateCriteria() method, which takes a persistent class Type as its only argument. This tells NHibernate to gear up to interact with the tables mapped to this object; asking for the List() property of the results returns all the instances of that criteria. In this case, we’ll get back a List containing instances of Department, fully populated from the database (including all the other persistent objects related to Department). This straightforward method is used to iterate through all instances of a class in your database. If you want to retrieve a specific instance from the database, you have to know the specific value of the identifier field for the target class that you are looking for. public Department getDepartment(int i) { Department d = null; try { ISession session = factory.OpenSession(); ITransaction tx = session.BeginTransaction(); d = (Department)session.Load(typeof(nhRegistration.Department), i); session.Close(); } catch (Exception ex) { tx.Rollback(); session.Close(); // handle exception. } return d; } Just remember to cast the results of session.Load() to the appropriate type, as what you get back is an Object. Finally, what if you want to save changes to an instance (or create a new instance)? Session provides two methods: Session.Save() for creating a new instance, and Session.Update() for modifying an existing instance. You have to keep the two separate; Session conflicts and database errors occur if you try to use the wrong method. In our interface, though, our DBMgr http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 12. TheServerSide.NET - Print Friendly Página 12 de 13 implementation only has one method, saveDepartment(Department dept). It doesn’t make much sense for such a simple application to force developers to distinguish between persisting a new object versus an existing one, so the interface only exposes that single entry point. In our implementation, however, we are still required to make that distinction. Here is a (altogether too simple) version: public void saveDepartment(Department dept) { try { ISession session = factory.OpenSession(); ITransaction tx = session.BeginTransaction(); if(dept.Id == 0) { session.Save(dept); } else { session.Update(dept); } tx.Commit(); session.Close(); } catch (Exception ex) { tx.Rollback(); session.Close(); // handle exception } } First, before we persist the instance, we determine if it is a new instance or modified pre-existing version. With a simple integer-based identification field, we can just check to see if it has a value of 0, which means it has no corresponding row in our database (remember our unsaved-value attribute above). You can imagine, though, that this logic breaks down in the face of more complicated identification fields. Once we make that determination, we invoke the correct method on Session to do the work for us. Other Concerns This article has been a whirlwind tour of NHibernate, giving you just the basics you’ll need to get started. Clearly, there is much I have left out, glossed over or hidden behind a veil of fog. In my next article, we’ll tackle some of those issues, like: l Parameterized queries in HQL (Hibernate Query Language) l Caching l Advanced collection semantics (lazy loading, bidirectional mapping) l Advanced session management (disconnected objects, SaveOrUpdate semantics) l Limiting configuration steps (only building the SessionFactory once) …and more. I hope this article has piqued your interest in the power of O/R mappers. Remember, NHibernate is just one of many, and if this looks interesting but not QUITE to your liking, there’s many more out there to choose from. Authors Justin Gehtland is a founding member of Relevance, LLC, a consultant group dedicated to elevating the practice of software development. He is the co-author of Windows Forms Programming in Visual Basic .NET (Addison Wesley, 2003) and Effective Visual Basic (Addison Wesley, 2001). Justin is an industry speaker, and instructor with DevelopMentor in the .NET curriculum. http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004
  • 13. TheServerSide.NET - Print Friendly Página 13 de 13 News | Discussions | Tech talks | Case studies | Articles | Media kit | Signup | About All Content Copyright ©2004 TheServerSide Privacy Policy http://www.theserverside.net/articles/printfriendly.tss?id=NHibernate 15/10/2004