Software Twist – Adrian Tosca Blog

Implementing a Simple Generic Repository with LinqToSql

Posted in Software Development by Adrian Tosca on 2009, April 17

The Repository pattern

The Repository is a design pattern often used in Domain Driven Design (DDD) to help the domain layer access data needed from the underlying persistence layer.

The Repository pattern was described by Martin Fowler as:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications decoratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.

In DDD the repository is tightly linked with the aggregate notion. The aggregate is a hierarchy of objects that are treated as a unit for the purpose of data changes. The aggregate components are accessed only from its root object. A repository is usually build around an aggregate.

As an example we may have a Car aggregate that has a collection of Wheels.

Car and Wheels Model

In our domain we will never refer to a wheel directly but first get a car and have access to its wheels.

Get Car Aggregate from Repository

Most of the time we need just a couple of operations to deal with aggregates on the repository.  With the above example we would have to implement in the repository methods to:

  • Add a new Car
  • Remove a Car
  • Get the Car by Id
  • Get a filtered list of Cars

Implementing this in LinqToSql is pretty straightforward but it has its catches.

Add and Remove

The simplest to implement are the add and remove methods:

    public class Repository<T> where T : class {
        CarsDataContext _dataContext = new CarsDataContext();
        public void Add(T entity) {
            DataContext.GetTable<T>().InsertOnSubmit(entity);
            DataContext.SubmitChanges();
        }
        public void Remove(T entity) {
            DataContext.GetTable<T>().DeleteOnSubmit(entity);
            DataContext.SubmitChanges();
        }
    }

Nothing special here. The generic GetTable of the LinqToSQL data context is used to insert/delete the entity and then SubmitChanges is called to send the changes to the database. The methods can be used like this:

    Repository<Car> carRepository = new Repository<Car>();

    // create a new car and add it
    Car newCar = new Car();
    carRepository.Add(newCar);

    // get an existingCar, then remove it
    Car existingCar = ...
    carRepository.Remove(existingCar);

Get By Id

Implementing the get by id method is a little more challenging. The first thing is to ensure that the model has the ‘Id’ notion. By default the LinqToSql classes do not have a direct way of exposing an identifier meta-data. We can have this by adding an interface and ensure the classes implements it:

    public interface IIdentifiable {
        int Id { get; }
    }
    public partial class Car : IIdentifiable {
    }

All the classes that need to be get by Id will have to implement the IIdentifiable interface. This is done in the code above by adding a partial class that implements the IIdentifiable interface. There is a catch here. If a consistent naming convention is used and all the classes have an ‘Id’ property then the above code is all we need.

With the classes prepared we can then write:

    public class Repository<T> where T : class, IIdentifiable {
        public T GetById(int id) {
            T entity = DataContext.GetTable<T>().SingleOrDefault(e => e.Id.Equals(id));
            return entity;
        }
    }

Please note the e.Id.Equals(id) above. LinqToSql does not know how to generate the == operator when interfaces are involved but it knows to generate the proper expression tree with Equals.

The GetById method can then be used like:

    Repository<Car> carRepository = new Repository<Car>();
    Car existingCar = carRepository.GetById(1);

The generated SQL contains what we expect, a parametrized query:

    exec sp_executesql N'SELECT [t0].[Id], [t0].[Make], [t0].[Year]
    FROM [dbo].[Car] AS [t0]
    WHERE [t0].[Id] = @p0',N'@p0 int',@p0=1

Getting Aggregate Elements

As LinqToSql supports lazy loading so all is needed is to access the elements from the root.

    Car car = carRepository.GetById(1);
    Console.WriteLine(car.Make);
    Console.WriteLine(car.Wheels.Count); // additional query will hit the database

Clean and easy. For more complex scenarios where one would need to control the loading behavior the DataLoadOptions of the LinqToSql can be used.

Get a Filtered List

The simplest to implement this is to allow expression filters as parameters:

    public IQueryable<T> GetByFilter(Expression<Func<T, bool>> filter) {
        return DataContext.GetTable<T>().Where(filter);
    }
    // and this can be used like:
    IQueryable<Car> cars = carRepository.GetByFilter(e => e.Year == 2009 && e.Make == "Ford");

An IQueryable is returned to allow simple UI integration. For example using a GridView with a LinqToSql source will automatically have sorting and paging implemented with this approach. The downside of this approach is that the DataContext will remain open up to the UI layer and this might introduce performance penalties. The alternative would be to return an IEnumerable instead and let the UI handle the pagination and sorting.

Conclusion

The solution presented is not without flaws. The biggest one is the tight link between the DB implementation and the model, forced by the LinqToSql architecture. There is also the inconvenient of having all primary keys named ‘Id’ and having to write partial classes for implementing the IIdentifiable interface. But there are also a couple of nice things like a very simple and clean usage, the possibility to use generics with aggregates and, maybe the best one, the possibility of avoiding boiler plate code.

Download the supporting code for this article (12.0 KB).

Advertisements

Adding Spark View Engine to ASP.NET MVC: A Step by Step Guide

Posted in Software Development by Adrian Tosca on 2009, March 29

The installation of Spark view engine is not difficult but it is better to know where to start. As currently there is no official installation guide, I put up a little list to help get started:

1. Download the spark view engine release zip archive

The release zip contains all the binaries, a Visual Studio integration msi and samples. The samples contain a lot of examples with the ASP.NET MVC framework.

2. Install SparkVsIntegration-1.0.39890.0-release.msi from the root folder of the zip archive.

The installer is a bit weird in the sense that does not say anything and closes after installation. If you do not receive any error is supposed to be correctly installed. To be  sure there are no problem with the installation, have all instances of Visual Studio closed. The VS integration of the engine is not great at the moment, be sure to check intelisense information on the official site. 

3. Copy the following binary files from Spark\Bin in the extracted zip archive  to a folder in your solution (usually ‘Dependencies’):

Spark.dll
Spark.pdb
Spark.Web.Mvc.dll
Spark.Web.Mvc.pdb

4. Add references in your web mvc project to Spark.dll and Spark.Web.Mvc.dll.

At this point the engine is ready to use, and only needs to be configured. For example configuration, the provided samples in the zip archive are very handy.

5. Open Global.asax.cs in the root folder of your application and add the following method:

        public static void RegisterViewEngine(ViewEngineCollection engines) {
            var settings = new SparkSettings();

            // comment this if you want to use Html helpers with the ${} syntax:
            // otherwise you would need to use the <%= %> syntax with anything that outputs html code
            settings.SetAutomaticEncoding(true); 

            settings
                .AddNamespace("System")
                .AddNamespace("System.Collections.Generic")
                .AddNamespace("System.Linq")
                .AddNamespace("System.Web.Mvc")
                .AddNamespace("System.Web.Mvc.Html")
                .AddNamespace("Microsoft.Web.Mvc");
                // Add here more namespaces to your model classes
                // or whatever classes you need to use in the views

            settings
                .AddAssembly("Microsoft.Web.Mvc")
                .AddAssembly("Spark.Web.Mvc")
                .AddAssembly("System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
                .AddAssembly("System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

            engines.Add(new SparkViewFactory(settings));
        }

The method is called on Application_Start to actually register the spark engine with the ASP.NET MVC view engines.

    protected void Application_Start() {
        RegisterViewEngine(ViewEngines.Engines);
        RegisterRoutes(RouteTable.Routes);
    }

and… done

At this point the engine is configured and ready to use. The simplest way to start using it is to rename one of the aspx views into .spark file and start replacing the code with the spark syntax. The beauty is that the two engines can work with no problem side by side so there is no need to replace all the pages at once with the spark syntax!

For example you could rename Home/Index.aspx to Home/Index.spark and replace the content with:

<h2>${Html.Encode(ViewData["Message"])}</h2>
To learn more about ASP.NET MVC visit
<a title="ASP.NET MVC Website" href="http://asp.net/mvc">http://asp.net/mvc</a>.

To enable the master pages you will need to add an Application.spark file in the Views/Shared folder. To use strongly typed views add the following at the beginning of the .spark file:

    <viewdata model="YourModelViewClass"/>

The samples in the spark binaries contain a lot more examples and more advanced stuff so be sure to check it out.

Combining Explicit Mappings and Conventions in Fluent NHibernate

Posted in Software Development by Adrian Tosca on 2009, March 28

Fluent NHibernate has got a lot of hype recently and for good reasons: the XML configuration is not the funniest part of using Hibernate. The big advantage of the framework is the ability to build up the NHibernate configuration in a type safe manner. But on top of that, the library has a number of features that greatly simplifies the initial work of configuration.

Automapping

The auto mapper mechanism can automatically map all the entities in the domain based on a set of conventions. 

ISessionFactory sessionFactory =
    Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2005.ConnectionString(
            cs => cs.Is("connection string"))
        .Mappings(m => m.AutoMappings.Add(
            AutoPersistenceModel.MapEntitiesFromAssemblyOf<Location>()))
        .BuildSessionFactory();

And that’s all. In this example the database is configured with SqlServer 2005 but it can be anything else of course. You get a set of of mappings based on a set of standard conventions. The auto-mapper has the possibility to override the default conventions. Unfortunately it is not always easy to both have a set of conventions and make adjustments where needed. In theory this sounds great but in practice there are always exceptions and before you know it you find yourself with a lot of weird ‘conventions’ that are made only to resolve a particular problem. Overriding the conventions only when needed also sound great but it can become a nightmare to maintain.

In practice a compromise between manual mappings and limited a set of conventions might be a better approach most of the time.

Mappings and conventions

The compromise is to build the normal mappings but only with the non repetitive code that is better to stay in conventions. You could have:

    public class Location {
        public virtual Guid Id { get; set; }
        public virtual string Name { get; set; }
        public virtual Country Country { get; set; }
    }

    public class LocationMapping : ClassMap<Location> {
        public LocationMapping() {
            Id(e => e.Id);
            Map(e => e.Name).Unique();
            References(e => e.Country).Not.LazyLoad();
        }
    }

And then have a number of conventions that are general for all the entities. For example we could have all id’s generated with the GuidComb generator:

    public class PrimaryKeyGeneratorConvention : IIdConvention {
        public bool Accept(IIdentityPart id) {
            return true;
        }
        public void Apply(IIdentityPart id) {
            id.GeneratedBy.GuidComb();
        }
    }

And all columns that are named ‘Name’ could have a certain storage column length:

    public class PropertyNameLengthConvention : IPropertyConvention {
        public bool Accept(IProperty property) {
            return property.Property.Name == "Name";
        }
        public void Apply(IProperty property) {
            property.WithLengthOf(255);
        }
    }

The following code will generate a configuration that reads the mappings and apply the conventions:

ISessionFactory sessionFactory =
    Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2005.ConnectionString(
            cs => cs.Is("connection string"))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<LocationMapping>()
        .ConventionDiscovery.AddFromAssemblyOf<PrimaryKeyGeneratorConvention>()
        .BuildSessionFactory();

I found that is better to avoid combining the convention in the same class even if they refer to the same piece of configuration. For example would be better to just make another convention PrimaryKeyNamingConvention if the primary key should be named ‘Id’.

The infamous RedirectFromLoginPage method

Posted in Software Development by Adrian Tosca on 2009, February 28

Do you happen to spent a lot more time than you expect on tasks that seemed simple enough? It happen to me. Last night. 3 more hours than expected.

The task was to add custom forms authentication to a web application I work on. I didn’t pay to much attention to the authentication as it was more important to first settle down the functional aspects of the application. But the time to do it has finally arrived. The plan was simple:

  1. Add a custom user class implementing the IPrincipal interface
  2. Add an encrypted cookie containing the serialized user data
  3. Check the cookie on AuthenticateRequest Event and set the custom user instance on HttpContext.Current.User

But something went wrong at point 2. The cookie just didn’t want to go to the browser. The code looks clear enough:

Response.Cookies.Add(new HttpCookie(userName, encryptedTicket));
FormsAuthentication.RedirectFromLoginPage(userName, false);

As I discovered (hours later if you recall) is that the RedirectFromLoginPage method does not do just what it says. I mean what would you expect to do. It just says ‘redirect from login page‘ isn’t it? It will do a redirect to the login page… well, not quite, as the MSDN documentation says:

If the CookiesSupported property is true, and either the ReturnUrl variable is within the current application or the EnableCrossAppRedirects property is true, then the RedirectFromLoginPage method issues an authentication ticket and places it in the default cookie using the SetAuthCookie method.

Yeap, that’s right, the method was overriding my cookie with an empty (but valid) one. After reading this, it was a simple fix:

Response.Cookies.Add(new HttpCookie(userName, encryptedTicket));
Response.Redirect(FormsAuthentication.GetRedirectUrl(userName, false));

There are a couple of lessons to learn from this experience:

  • Read the f…(snip) documentation.
  • Always check the assumptions, even the ones that look obvious true. 
  • Don’t do like them. The RedirectFromLoginPage does two things (redirects and sets a default cookie) breaking the separation of concern principle.
Tagged with: ,

Comments Off on The infamous RedirectFromLoginPage method