Login or Sign Up to become a member!

EXPERTS, INFORMATION, IDEAS & KNOWLEDGE

Social bookmarker Add this

Your profile

Search

November 2008
Mon Tue Wed Thu Fri Sat Sun
 << <   > >>
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

XML Feeds

Tags: nhibernate

All the LessThanDot Journals

My Path to the Dark Side part 4 - the Repositories

by AlexCuse


Permalink 28 Jul 2008 07:07 , Categories: Microsoft Technologies, C# Tags: c#, nhibernate, unit testing

Previous posts can be found here:

Setting up the repositories for our objects is where this really starts to get fun for me. This is what allows us to work with the persisted objects so easily from our application code, without all the SQL getting in the way. The first thing we want to think about here is what we need the repository to do. Add/Delete/Update all come to mind of course. As well as retrieval of single objects and collections. These will be pretty much standard behaviors across most of our objects. So lets’ look at the interface first:

  1. using System;
  2. using System.Collections.Generic;
  3. using RecipeTracker.Model;
  4.  
  5. namespace RecipeTracker.Interfaces
  6. {
  7.     public interface IRecipeRepository
  8.     {
  9.         void Add(Recipe recipe);
  10.         void Update(Recipe recipe);
  11.         void Remove(Recipe recipe);
  12.         Recipe GetByID(int id);
  13.         ICollection<Recipe> GetByFamily(string family);
  14.         ICollection<Recipe> GetAll();
  15.         void Dispose();
  16.     }
  17. }

Looking at all those methods, there is really only one (GetByFamily) that we won’t need for any repository that we create. So we can put all the other methods into a BaseRepository class. We will need use generics so we can return all the different types however. But first, we need to get a session, so we can add a class for that.

  1. using System;
  2. using NHibernate;
  3. using NHibernate.Cfg;
  4.  
  5. namespace RecipeTracker.Repositories
  6. {
  7.     public class SessionProvider<T> where T:new()
  8.     {
  9.         private static ISessionFactory _sessionFactory;
  10.  
  11.         private static ISessionFactory SessionFactory
  12.         {
  13.             get
  14.             {
  15.                 if (_sessionFactory == null)
  16.                 {
  17.                     var configuration = new Configuration();
  18.                     configuration.Configure();
  19.                     configuration.AddAssembly(typeof(T).Assembly);
  20.                     _sessionFactory = configuration.BuildSessionFactory();
  21.                 }
  22.  
  23.                 return _sessionFactory;
  24.             }
  25.         }
  26.  
  27.         public static ISession OpenSession()
  28.         {
  29.             return SessionFactory.OpenSession();
  30.         }
  31.     }
  32. }

The SessionFactory part should look familar from part 3, the only difference here is that we are initializing the configuration using TypeOf(T) to determine which assembly to find the configuration in rather than TypeOf(MyType). We could probably get away with the latter for this purpose, because there probably won’t be more than one assembly in the application, but why be lazy right? After all, we do need to use generics to deal with the return types anyways.

So now this little bit of code doesn’t need to be handled by our repository, and it can focus on what it does best. So here’s the BaseRepository, it’s nice and simple since it doesn’t need to get its’ own sessions anymore:

  1. using System;
  2. using System.Collections.Generic;
  3. using NHibernate;
  4. using NHibernate.Cfg;
  5.  
  6. namespace RecipeTracker.Repositories
  7. {
  8.     public abstract class BaseRepository<T> where T: new()
  9.     {
  10.         protected ISession _session = SessionProvider<T>.OpenSession();
  11.  
  12.         public T GetByID(int id)
  13.         {
  14.             return _session.Get<T>(id);
  15.         }
  16.  
  17.         public ICollection<T> GetAll()
  18.         {
  19.             var products = _session
  20.                 .CreateCriteria(typeof(T))
  21.                 .List<T>();
  22.             return products;
  23.         }
  24.  
  25.         public void Update(T toUpdate)
  26.         {
  27.             using (ITransaction transaction = _session.BeginTransaction())
  28.             {
  29.                 _session.Update(toUpdate);
  30.                 transaction.Commit();
  31.             }
  32.         }
  33.  
  34.         public void Add(T toAdd)
  35.         {
  36.             using (ITransaction transaction = _session.BeginTransaction())
  37.             {
  38.                 _session.Save(toAdd);
  39.                 transaction.Commit();
  40.             }
  41.         }
  42.  
  43.         public void Remove(T toRemove)
  44.         {
  45.             using (ITransaction transaction = _session.BeginTransaction())
  46.             {
  47.                 _session.Delete(toRemove);
  48.                 transaction.Commit();
  49.             }
  50.         }
  51.  
  52.         public void Dispose()
  53.         {
  54.             _session.Close();
  55.             _session.Dispose();
  56.         }
  57.     }
  58. }

Now, look how simple that is to do what we need with our object? No building SQL queries, no creating parameter arrays, or anything. A nice simple bit of code that does just what we need it to do, without all the hassles. We just need a session and the simple commands that it offers, and we can do anything we need. Beautiful, right?

But what if we wanted to do something like get all recipes from a certain family? This will be specific to the object type we need, so we can do that in our implementation of the baseclass (hey, gotta have something in there right!). And this is in fact all that our RecipeRepository class has, one method:

  1. using System;
  2. using System.Collections.Generic;
  3. using RecipeTracker.Model;
  4. using NHibernate;
  5.  
  6. namespace RecipeTracker.Repositories
  7. {
  8.     public class RecipeRepository : BaseRepository<Recipe>, Interfaces.IRecipeRepository, IDisposable
  9.     {
  10.         public ICollection<Recipe> GetByFamily(string family)
  11.         {
  12.                 var products = _session
  13.                     .CreateCriteria(typeof(Recipe))
  14.                     .Add(NHibernate.Criterion.Expression.Eq("Family", family))
  15.                     .List<Recipe>();
  16.                 return products;
  17.         }
  18.     }
  19. }

This is some wacky looking code at first. It kind of reminds me of Linq, but what its’ called is HQL (Hibernate Query Language). I haven’t really gotten into it all that much, so I don’t feel qualified to speak about it in detail, but I do find it kinda cool. It may not be as easy as Linq, where you could do a nice Linq query such as

recipeList.Where(n => n.Family = family)

But remember this needs to work on older framework versions as well. I think the HQL is reasonably succinct, and even somewhat elegant. After all reading that you can just about instantly tell what it does. It just creates a criteria on the session for Recipes, and then defines the expression to be evaluated (table.Family = family). Pretty cool. We could probably figure out how to do this with generics pretty easily, but I figure this kind of method is going to be tied to your specific type, and you want to have a descriptive name, and all that.

So after all this I think we are ready to set up some tests. This will be on the next page (damn I’m getting long-winded!)

Pages: 1 · 2

2 comments »Send a trackback » 412 views

My Path to the Dark Side part 3 - Testing the Schema

by AlexCuse


Permalink 21 Jul 2008 09:59 , Categories: Microsoft Technologies, C# Tags: c#, nhibernate, unit testing

Previous posts can be found here:

In part two we set up our domain model. Now, before we can test nhibernate’s ability to work with and persist objects, we need to ensure that we’ve defined our schema well enough that NHibernate can create the Schema for us (since that was kind of the point). Now is where NUnit starts to become very useful.

First step we’re going to take to set up NUnit is to add another project to our solution. I named this project the very creative RecipeTracker.Tests. When setting up this project, it is important to add all the same references as we used in the main project. In addition we need to add a reference to the main project itself and a reference to nunit.framework. For the main project, we’ll need to again set the “CopyLocal” option to true. Finally, we also need a copy of our Sql Compact database in this project.

Our first unit test will just be to see that we can export the schema. Here it is:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using NHibernate.Cfg;
  6. using NHibernate.Tool.hbm2ddl;
  7. using NUnit.Framework;
  8. using RecipeTrackerPartOne;
  9.  
  10. namespace RecipeTrackerPartOne.Tests
  11. {
  12.     [TestFixture]
  13.     public class GenerateSchema_Fixture
  14.     {
  15.         [Test]
  16.         public void Can_generate_schema()
  17.         {
  18.             var cfg = new Configuration();
  19.             cfg.Configure();
  20.             cfg.AddAssembly(typeof(Model.Recipe).Assembly);
  21.  
  22.             new SchemaExport(cfg).Execute(false, true, false, false);
  23.         }
  24.     }
  25. }

There’s a lot of new stuff going on here. Most noticeable is the directive to use nunit.framework, and the attributes added to our class and our methods. These attributes are used when we load the project into NUnit, so that the NUnit application knows which code to execute as a test. We need to identify our class as a TestFixture, then our method within the class as a Test (this setup allows us to include supporting code that is not necessarily a test). Also notable is the directive to use NHibernate.Tool.hbm2ddl. This is what allows NHibernate to create the schema for us (by converting Hibernate mappings to Data Definition Language).

The most interesting line, as far as I am concerned, is the “AddAssembly” line. This is what associates our Configuration with a given assembly, and therefore that assembly’s hibernate.cfg.xml file. So, what we are really testing here is really the schema we have defined in the xml file.

If everything is set up right, when you fire up the NUnit GUI, load the RecipeTracker.Tests assembly, and run the test, you should see a nice green bar. Unfortunately, we broke the first rule of Unit Testing, that the first time we run a test it should fail. Well, I didn’t, but I wanted to spare you gentle readers some of the pain of wrestling with the mapping file. But fear not, because now it is time to experience the joy that is the red, “you screwed up” bar. Remember, we want to confirm that NUnit will in fact tell us when we do screw up!

For this part we’ll need to start setting up our repositories to move the objects to and from the database. This gets pretty involved, so this will have to be continued in Part 4.

Here is the sample project (so far). Next one will be where it gets interesting! Sample Project - Part 1

Leave a comment »Send a trackback » 278 views

My Path to the Dark Side part 2 - The Domain Model

by AlexCuse


Permalink 15 Jul 2008 06:24 , Categories: Microsoft Technologies, C# Tags: c#, nhibernate, unit testing

In part one we discussed what has brought me to the shameful point of using an object-relational mapper. At the risk of being ostracized from the database community, I really think this is going to be helpful for my project.

The next step is to actually build up the domain model, and set up the mappings for NHibernate. I won’t be pasting all the code in here, but I will be attaching the project itself to the next post if anyone’s interested. I ended up working ahead of myself so I had to kind of go backwards to create a “part one” project (I got too carried away with working, forgot to check in for a few days :( ). First let us look at the “recipe” domain object, which is at the center of everything.

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace RecipeTrackerPartOne.Model
  7. {
  8.     public class Recipe
  9.     {
  10.         private Int32 _id;
  11.         private String _name;
  12.         private DateTime _attemptDate;
  13.         private String _family;
  14.         private String _style;
  15.         private Double _originalGravity;
  16.         private Double _finalGravity;
  17.         private Int32 _boilTime;
  18.         private Int32 _fermentationTime;
  19.         private Int32 _fermentationTemperature;
  20.         private Int32 _secondaryFermentationTime;
  21.         private String _yeast;
  22.         private Int32 _batchSize;
  23.         private String _note;
  24.         private Person _brewer;
  25.  
  26.         //rating info
  27.         private IList<Impression> _recipeImpressions;
  28.  
  29.  
  30.         //list of ingredients
  31.         private IList<Ingredient> _ingredientsUsed;
  32.  
  33.         public Recipe()
  34.         {
  35.             _recipeImpressions = new List<Recipe>();
  36.             _ingredientsUsed = new List<Recipe>();
  37.         }
  38.  
  39.         public Int32 Id
  40.         {
  41.             get { return _id; }
  42.             set { _id = value; }
  43.         }
  44.  
  45.         public String Name
  46.         {
  47.             get { return _name; }
  48.             set { _name = value; }
  49.         }
  50.  
  51.         public DateTime AttemptDate
  52.         {
  53.             get { return _attemptDate; }
  54.             set { _attemptDate = value; }
  55.         }
  56.  
  57.         public String Family
  58.         {
  59.             get { return _family; }
  60.             set { _family = value; }
  61.         }
  62.  
  63.         public String Style
  64.         {
  65.             get { return _style; }
  66.             set { _style = value; }
  67.         }
  68.  
  69.         public Double OriginalGravity
  70.         {
  71.             get { return _originalGravity; }
  72.             set { _originalGravity = value; }
  73.         }
  74.  
  75.         public Double FinalGravity
  76.         {
  77.             get { return _finalGravity; }
  78.             set { _finalGravity = value; }
  79.         }
  80.  
  81.         public Int32 BoilTime
  82.         {
  83.             get { return _boilTime; }
  84.             set { _boilTime = value; }
  85.         }
  86.  
  87.         public Int32 FermentationTime
  88.         {
  89.             get { return _fermentationTime; }
  90.             set { _fermentationTime = value; }
  91.         }
  92.  
  93.         public Int32 FermentationTemperature
  94.         {
  95.             get { return _fermentationTemperature; }
  96.             set { _fermentationTemperature = value; }
  97.         }
  98.  
  99.         public Int32 SecondaryFermentationTime
  100.         {
  101.             get { return _secondaryFermentationTime; }
  102.             set { _secondaryFermentationTime = value; }
  103.         }
  104.  
  105.         public String Yeast
  106.         {
  107.             get { return _yeast; }
  108.             set { _yeast = value; }
  109.         }
  110.  
  111.         public Int32 BatchSize
  112.         {
  113.             get { return _batchSize; }
  114.             set { _batchSize = value; }
  115.         }
  116.  
  117.         public String Note
  118.         {
  119.             get { return _note; }
  120.             set { _note = value; }
  121.         }
  122.  
  123.         public IList<Impression> RecipeImpressions
  124.         {
  125.             get { return _recipeImpressions; }
  126.             set { _recipeImpressions = value; }
  127.         }
  128.  
  129.         public IList<Ingredient> IngredientsUsed
  130.         {
  131.             get { return _ingredientsUsed; }
  132.             set { _ingredientsUsed = value; }
  133.         }
  134.  
  135.         public Person Brewer
  136.         {
  137.             get { return _brewer; }
  138.             set { _brewer = value; }
  139.         }
  140.  
  141.         public void AddIngredient(Model.Ingredient i)
  142.         {
  143.             _ingredientsUsed.Add(i);
  144.         }
  145.  
  146.         public void RemoveIngredient(Model.Ingredient i)
  147.         {
  148.             _ingredientsUsed.Remove(_ingredientsUsed.Single<Model.Ingredient>(x => x == i));
  149.         }
  150.  
  151.         public void AddImpression(Model.Impression i)
  152.         {
  153.             _recipeImpressions.Add(i);
  154.         }
  155.  
  156.         public void ChangeBrewer(Model.Person p)
  157.         {
  158.             _brewer = p;
  159.         }
  160.  
  161.         public Double AlcoholByWeight()
  162.         {
  163.             return (76.08 * Convert.ToDouble(_originalGravity - _finalGravity)) / (1.775 - Convert.ToDouble(_originalGravity));
  164.         }
  165.  
  166.         public Double AlcoholByVolume()
  167.         {
  168.             return AlcoholByWeight() * (Convert.ToDouble(_finalGravity) / 0.794);
  169.         }
  170.     }
  171. }

Its’ a pretty simple object, it has some data, and just a couple methods. The most interesting properties to look at here are RecipeImpressions, IngredientsUsed, and Brewer. Why are these the most interesting? Because each is of another type (Impression, Ingredient, and Person, respectively) that we will need to persist in our database. Now that we’ve got an object in mind, lets’ start thinking about setting this up.

Setting Up The Project

We need to do some housekeeping before we proceed.

First, adding our references to the following:

  • NHibernate (I used the most recent beta version since this is not exactly a critical app)
  • Sql Server Compact (System.Data.SqlServerCe)


Once these references are added, we need to make sure both have their “Copy Local” property set to True (by default this will be false for SqlServerCe).

After adding the references, we need to add a Sql Server Compact database to our project (in the root directory). I called it “BeerRecipes.sdf". You can skip that Data Set Wizard thing that pops up.

Once this is done, we are ready to set up NHibernate.

Setting Up NHibernate Configuration

NHibernate is driven by an xml file added to the project called hibernate.cfg.xml. So what are you waiting for, add that file! (again to the root directory) I promise to be here when you get back. Ok, that was not so hard, right? Now, what do we need to add to this file? For this simple example, not all that much. We need to define a “session-factory” class, which is basically a more sophisticated connection string. Properties we need to set include:

  • Provider
  • Dialect - SQL “flavor” for NHibernate to use
  • Driver - Driver NHibernate uses to identify (and connect to) Provider
  • Connection String - where is the database located?
  • Show Sql - whether to output SQL to the console

So, what does this file look like? Glad you asked:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  3.   <session-factory>
  4.     <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
  5.     <property name="dialect">NHibernate.Dialect.MsSqlCeDialect</property>
  6.     <property name="connection.driver_class">NHibernate.Driver.SqlServerCeDriver</property>
  7.     <property name="connection.connection_string">Data Source=BeerRecipes.sdf</property>
  8.     <property name="show_sql">true</property>
  9.   </session-factory>
  10. </hibernate-configuration>

For the most part these are pretty self explanatory. The only one I’ve really been messing with is the “show_sql” property, which controls whether the sql generated by NHibernate is output to the console or not. I like to set this to true when I am running my unit tests manually, so I can look at the SQL in case a test fails. Otherwise, I would set it to false.

Setting up NHibernate Mappings

This is where it gets interesting. We now need to tell NHibernate which tables within the database to store our objects in, and define any relationships between the objects. We also need to tell NHibernate which assembly to look for our types in. We’ll do this in a mappings file. I created a special “mappings” folder within the project for this. The naming convention for these files is myfile.hbm.xml. Because I’m lazy I just created one file, called RecipeMappings.hbm.xml and threw everything in there. So lets’ just get the whole thing on the table first, then talk about it (only 2 classes included for brevity’s sake, but they’re all there I swear).

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
  3.                    assembly="RecipeTracker"
  4.                    namespace="RecipeTracker.Model">
  5.  
  6.   <class name="Recipe" table="Recipes">
  7.     <id name="Id" column="Id" type="Int32">
  8.       <generator class="native" />
  9.     </id>
  10.     <property name="Name" type="String(35)"/>
  11.     <!– we can also do without specifycing type and let nhibernate do the work–>
  12.     <property name="AttemptDate"/>
  13.     <property name="Family"/>
  14.     <property name="Style"/>
  15.     <property name="OriginalGravity"/>
  16.     <property name="FinalGravity"/>
  17.     <property name="BoilTime"/>
  18.     <property name="FermentationTime"/>
  19.     <property name="FermentationTemperature"/>
  20.     <property name="SecondaryFermentationTime"/>
  21.     <property name="Yeast"/>
  22.     <property name="BatchSize"/>
  23.     <property name="Note"/>
  24.     <!– nhibernate will set up a foreign key relationship between tables for us –>
  25.     <bag name="IngredientsUsed" cascade="all" lazy="true">
  26.       <key column="RecipeID"/>
  27.       <one-to-many class="Ingredient"/>
  28.     </bag>
  29.    
  30.     <!– lazy = true is default, don’t necessarily need it–>
  31.     <bag name="RecipeImpressions" cascade="all">
  32.       <key column="RecipeID"/>
  33.       <one-to-many class="Impression"/>
  34.     </bag>
  35.  
  36.     <many-to-one name="Brewer" column="Brewer" class="Person"/>
  37.  
  38.   </class>
  39. </hibernate-mapping>

The first item of interest here is the “hibernate-mapping” tag. This obviously is responsible for identifying the file as an NHibernate mapping file. Its’ also handy to be able to define the assembly and namespace in this tag as well. This is similar to a “using” directive in C# code, in that you won’t need to specify the assembly or namespace for each class you define.

After this, the class definitions are fairly straightforward. It is important to note that we need to specify the table that each class maps to however. In this example we are not specifying the data width for any of our columns of type “string” after the first one. This is because we will be relying on NHibernate to create our schema.

Its’ also important to note that we need to define an Id column for each type. While we won’t really be using this in our programming, NHibernate needs it to keep track of objects, and manage the relationships.

Finally, we get down to where the mappings are established. As we saw in the domain diagram in part 1, each recipe is related to three other types in the application. A recipe can have any number of Ingredients, any number of Impressions, and one brewer (of type Person). The first two relationships need to be defined as one to many, and the third as a many to one (because one brewer could have any number of recipes). We used a “bag” because this corresponds to an IList. You can also use “set” which corresponds to an IEnumerable.

Now, we have defined our domain, and thus our database schema. Next part is to set up our first unit test, to ensure that NHibernate can create the schema we’ve defined.

Need help with C#? Come and ask a question in our C# Forum

Leave a comment »Send a trackback » 507 views

My Path to the Dark Side part 1 - The Beginning

by AlexCuse


Permalink 03 Jul 2008 05:30 , Categories: Microsoft Technologies, C# Tags: c#, nhibernate, unit testing

For a while now, I’ve been brewing my own beer. Being a programmer, when I’m brewing of course I also need a way to store my recipes, and how they turn out. So I have a simple application I wrote that most recently uses SQL Server Compact edition for its database.

Recently I was trying to make some improvements to my domain in this application (namely, separating the “Impression” information from the recipe itself so that I could allow my special lady, and anyone else who drinks one of my beers, weigh in with their impressions of it). But I found myself getting incredibly bogged down in all the ad-hoc SQL that the program must maintain (SQL Server Compact doesn’t support stored procedures). Because I am used to using stored procs for everything, I’m also used to having a very simple and clean DAL. The necessity to create queries to insert/update each object type that I was trying to persist was a new one to me, and I found it most distasteful (why should I need 45 lines of code to update my recipe?). It makes for a lot of unnecessary complexity in my application code.

With stored procs, I think this is acceptable. Just define the proc name, assign your parameters, and run it. This also gives you the benefit of being able to limit changes to the database only in many situations. However with SQL Server Compact, it really blows. I need to make my changes to the database, then I need to go through all my application code and recreate queries there. Then I have to test it. Not fun! I found I was spending much more time modifying and testing the data access code to to deal with the redesigned objects than I was modifying the objects themselves. For a database that was doing so little actual work, this is unacceptable to me.

Instead of trying to modify this application, I decided I will start from scratch, and use what I have learned from the first time around to create a better and more maintainable application. With this decision made, the question becomes “How can I do this?". I’ve been learning a lot about test-driven development in school, so this will give me a chance to apply that knowledge, using nUnit. But will applying TDD really help me to clean up this data access crap? I don’t think so. I suppose I could write my own class to generate the updates, etc…, but I do enough work at work. So I need a way to do this more easily.

Luckily my esteemed colleague Chrissie1 has been preaching the gospel of nHibernate to me for a long time now. I’ve never really bought in because most of my applications at work rely heavily on the database to do actual work. But for this application, I really only need to use the database to persist my objects. Maybe a tool like nHibernate could really help me here?

I’ve started down the road, and I think that it really will. This series of blogposts will contain my ramblings as I travel down the path of recreating this application. We’ll start with development of the domain model. The program has a very simple domain model (Recipe, Ingredient, Impression, and Person) which will make it a good way to demonstrate new concepts without getting bogged down in complex application design. Here is a diagram of the application’s problem domain:

The goals of this exercise will be:

  • Eliminate or minimize application’s dependency on the database.
  • Allow the application to easily work with another database.
  • Produce more reliable code by using Test Driven Development methodology
  • Minimize the effort required to alter the way the application manages and persists domain objects

Once I’m done with this, I still have the actual program to write, but there will be some follow up posts discussing how much easier (it had better be) to develop the UI. Hopefully this series of posts will leave the reader (and me!) with a good understanding of the basics of nHibernate and nUnit.

2 comments »Send a trackback » 675 views