Wednesday, October 2, 2013

Database Table Mapping - Fluent NHibernate

- 0 comments
Maintaining database data and interactions is a tough and time-consuming task. Object Relational Mappers (ORMs) were devised to solve precisely that problem. They allow developers to map database tables to object-oriented classes and use modern refactoring tools to make changes to the code-base. This allows for more rapid development and streamlined maintenance.

Initially, we used Castle ActiveRecord as an abstraction layer for our database. This allowed us to use attributes to map the properties of our object entities to columns in the database tables. When we decided  to move away from ActiveRecord due to lack of development progress, we used a tool to generate straight NHibernate XML mapping files from the existing mappings. These were all well and good until they actually had to be edited. Every change to a property required us to track down the related XML file and update the mapping information.

We decided to try out Fluent Nhibernate for our mappings. Fluent used C# Linq Expressions to define the relationships between entity tables and their behavior when updating the database. The beauty of Fluent was that we could still keep the XML mapping files around while we slowly moved to the more maintainable scheme. We did this by adding the configuration code shown below.

public static Configuration ApplyMappings(Configuration configuration)
{
   
     return Fluently.Configure(configuration)
         .Mappings(cfg =>
         {
             cfg.HbmMappings.AddFromAssemblyOf<Enrollment>();
             cfg.FluentMappings.AddFromAssemblyOf<Enrollment>();
         }).BuildConfiguration();
}

Then, objects could be easily mapped in code rather than using attributes or XML. We could map collections and even specify cascade behaviors for the related objects. See the example of mapping basic properties, collections and related objects below.

public class Syllabus
{
      public virtual Guid Id { get; set; }


      public virtual string Title { get; set; }


      public virtual IList<enrollment> Enrollments { get; set; }
}

public class SyllabusMapping : FluentNHibernate.Mapping.ClassMap<Syllabus>
{
      public SyllabusMapping()
      {
           Table("Syllabus");

           Id(x => x.Id)
               .GeneratedBy.Assigned()
               .UnsavedValue(new Guid("DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF"));

           Map(x => x.Title).Column("Title");

           HasMany(x => x.Enrollments)
               .KeyColumn("Syllabus")
               .LazyLoad()
               .Inverse()
               .Cascade.Delete();
     }
}

public class Enrollment
{
     public virtual Guid Id { get; set; }


     public virtual Syllabus Syllabus { get; set; }


     public virtual ActivityResultEnum Result { get; set; }
}

public class EnrollmentMapping : FluentNHibernate.Mapping.ClassMap<Enrollment>
{
     public EnrollmentMapping()
     {
          Table("Enrollments");

          Id(x => x.Id)
               .GeneratedBy.Assigned()
               .UnsavedValue(new Guid("DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF"));

          Map(x => x.Result).Column("Result").CustomType<ActivityResultEnum>();

          References(x => x.Syllabus)
               .Column("Syllabus")
               .Access.Property()
               .LazyLoad();

     }
}

One problem we faced was that our object graph used inheritance heavily. We were a little apprehensive about how complex it would be to translate that to Fluent. Fortunately for us, the solution was relatively straightforward. It required creating a base mapping class and using a discriminator column to distinguish the types.

public class SyllabusMapping : FluentNHibernate.Mapping.ClassMap<Syllabus>
{
     public SyllabusMapping()
     {
         Table("Syllabus");

         Id(x => x.Id)
             .GeneratedBy.Assigned()
             .UnsavedValue(new Guid("DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF"));

         Map(x => x.Title).Column("Title");

         HasMany(x => x.Enrollments)
             .KeyColumn("Syllabus")
             .LazyLoad()
             .Inverse()
             .Cascade.Delete();

         DiscriminateSubClassesOnColumn<SyllabusTypeEnum>("SyllabusType", SyllabusTypeEnum.Unknown); // Allows sub-classes
     }
}


public class Section : Syllabus
{
     public virtual string SectionNumber { get; set; }
}

public class SectionMapping : FluentNHibernate.Mapping.SubclassMap<Section>
{
     public SectionMapping()
     {
         DiscriminatorValue(SyllabusTypeEnum.Section);

         Map(x => x.SectionNumber).Column("SectionNumber");
     }
}

public class TrainingPlan : Syllabus
{
     public virtual int RequirementTotal { get; set; }
}

public class TrainingPlanMapping : FluentNHibernate.Mapping.SubclassMap<TrainingPlan>
{
     public TrainingPlanMapping()
     {
         DiscriminatorValue(SyllabusTypeEnum.TrainingPlan);

         Map(x => x.RequirementTotal).Column("RequirementTotal");
     }
}

Moving forward, this will allow us to refactor code more easily and maintain the system while adding new features. We will be able to focus on new features rather than spending all our time searching for enigmatic mappings. With Fluent NHibernate, we were able to move from XML files to a robust, refactor-friendly solution. Win.

About NexPort Solutions Group
NexPort Solutions Group is a division of Darwin Global, LLC, a systems and software engineering company that provides innovative, cost-effective training solutions and support for federal, state and local government, as well as the private sector.
[Continue reading...]

Building a mobile site with JQueryMobile

- 0 comments
With the sales of tablets to eclipse computer sales within the next few years, as well as the growing adoption of touchscreen computers, we decided to create a version of the UI that provides better support for touch screens via larger interactive elements, as well better scalability over a range of resolutions.

To accomplish this, we decided to go with JQueryMobile. JQueryMobile is a natural choice since we are already making use of both JQuery and JQueryUI. Integration between the three of them seems to be rather good.

The Good

The JQueryMobile ThemeRoller will allow for the easy creation of themes, which will now effect more elements then before, providing organizations with greater customization capabilities.

JQueryMobile does a good job of handling a multitude of resolutions. It (mostly) manages to reflow intelligently to provide for a good user interface even if the screen resolution is limited.

JQueryMobile manages to provide good compatibility with legacy browsers, opening the possibility of providing a unified UI across both the desktop, as well as mobile market.


The Bad

JQueryMobile provides limited grid support, and does not play terribly nice with other grid frameworks. We are now using rwdgrid, and some resolutions have already caused issues with forms and had to be manually tweaked.

A lot of the currently existing styles clash with new styles. Determining which styles need to go and which can stay is troublesome.

JQueryMobile should be loaded at the top of the page to provide its styling as the page is loaded, rather then modifying it afterwards. At the same time, JQueryUI seems to not play nice if it is loaded after JQueryMobile and now needs to be loaded in the beginning, too.



In the long run, JQueryMobile seems to be a great choice for providing a mobile interface, and possibly a unified interface. It makes creating a mobile website almost as simple as generating a normal website and loading a few extra styles ans scripts.

About NexPort Solutions Group
NexPort Solutions Group is a division of Darwin Global, LLC, a systems and software engineering company that provides innovative, cost-effective training solutions and support for federal, state and local government, as well as the private sector.
[Continue reading...]
 
Copyright © . NexPort Solutions Engineering Blog - Posts · Comments
Theme Template by BTDesigner · Powered by Blogger