Monthly Archives: January 2013

Support from YourKit

YourKit has kindly donated open source licenses to the MicroLite development team, we will be using them to profile MicroLite to make it even better in future versions.

Future posts will examine the profiler and what improvements we have made as a result.

Advertisements

New Infrastructure Interfaces

As part of MicroLite 3.0, two new interfaces were added to the MicroLite.Infrastructure namespace:

IHaveSession and IHaveReadOnlySession

These interfaces are implemented by the controllers in the ASP.NET MVC and ASP.NET WebApi extensions and the MicroLiteSessionAttribute for each extension checks against the interfaces rather than the base controllers.

This means that if you want to, you can use the extensions without having to inherit from the base controllers.

// Instead of having to do this:
public HomeController : MicroLiteController
{
...
}

// You can do this:
public HomeController : SomeOtherController, IHaveSession
{
...
}

This allows you to use the extensions in a scenario where you cannot control the base controller you are using or if you just don’t want to have to inherit from the base MicroLite controller for any reason.

MVC and WebApi extensions

If you use the MVC or WebApi extensions for MicroLite and you use an ISession or IReadOnlySession for every action (method) on your controllers, instead of applying the [MicroLiteSession] to each controller or method you can simply register it in GlobalFilters so that it is invoked for every controller action.

GlobalFilters.Filters.Add(new MicroLiteSessionAttribute());

You can still add a [MicroLiteSession] to specific controller actions if you want to use an Isolation Level or transaction style which differs from the default specified in GlobalFilters:

public class HomeController : MicroLiteController
{
    public ActionResult Index()
    {
        // For this action, this.Session will be resolved using the configuration of 
        // the MicroLiteSessionAttribute in GlobalFilters.
    }

    [MicroLiteSession(AutoManageTransaction = false)]
    public ActionResult Index2()
    {
        // For this action, we want to do something specific with the transaction so we add the
        // MicroLiteSessionAttribute to this method to override the default configuration.
        using (var transaction = this.Session.BeginTransaction())
        {
            ...
        }
    }
}

Read Only Session

One of the main new features in MicroLite 3.0 is the Read Only Session. This allows you to have access to your database in a read only manner. A new interface IReadOnlySession has been introduced and the query portion of the ISession interface moved to it (ISession extends IReadOnlySession so it still looks the same as you are used to in earlier versions of MicroLite).

The Session interfaces now look like this:

MicroLite 3 Session Interfaces

The ISessionFactory has been updated and now has an additional method to open a read only session:

MicroLite 3 Session Factory

As you can see, Fetch, Paged, Projection and Single are all exposed under IReadOnlySession while Delete, Insert and Update are only available under ISession.

If you use the ASP.NET MVC or ASP.NET WebApi extensions, there are MicroLiteReadOnlyController/MicroLiteReadOnlyApiController available in addition to the standard MicroLiteController/MicroLiteApiController.

Using PostgreSQL

One of the updates in MicroLite 3.0 was support for PostgreSQL, however there are a couple of things you need to do if you wish to use PostgreSQL which you don’t for MS SQL. This is due to the fact that the .NET framework supports MS SQL natively, whereas the PostgreSQL implementations of the System.Data classes are provided by pgfoundry.org.

The easiest way to get started is to install the Npgsql NuGet package, although you can download and install it from pgfoundry.org if you don’t/can’t use NuGet.

As usual you will still need to add a named connection string to your app.config:

<connectionStrings>
    <add name="PostgreSqlTest"
         connectionString="Server=localhost;Database=database;User Id=User;Password=Pswd;"
         providerName="Npgsql" />
</connectionStrings>

You also need to add another section to your app.config so that the .NET framework knows about the Npgsql provider:

<system.data>
    <DbProviderFactories>
      <remove invariant="Npgsql" />
      <add name="PostgreSQL Data Provider"
           invariant="Npgsql"
           description=".Net Data Provider for PostgreSQL"
           type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
    </DbProviderFactories>
</system.data>

Make sure that the version specified matches the version you have installed or you will get an exception thrown by the .NET runtime at startup when it tries to resolve the assembly.

Then finally, in you application startup, you need to call the overload method for ForConnection so that you can specify the PostgreSqlDialect:

var sessionFactory = Configure
    .Fluently()
    .ForConnection(connectionName: "PostgreSqlTest", sqlDialect: "MicroLite.Dialect.PostgreSqlDialect")
    .CreateSessionFactory();

This article was written for version 3.0.0 of the MicroLite framework.

Update

As of MicroLite 4.0.1, use the ForPostgreSqlConnection method instead:

var sessionFactory = Configure
    .Fluently()
    .ForPostgreSqlConnection("PostgreSqlTest")
    .CreateSessionFactory();

Using MySQL

One of the updates in MicroLite 3.0 was support for MySQL, however there are a couple of things you need to do if you wish to use MySQL which you don’t for MS SQL. This is due to the fact that the .NET framework supports MS SQL natively, whereas the MySQL implementations of the System.Data classes are provided by MySQL.com.

The easiest way to get started is to install the MySQL.Data NuGet package, although you can download and install it from MySQL.com if you don’t/can’t use NuGet.

As usual you will still need to add a named connection string to your app.config:

<connectionStrings>
    <add name="MySQLTest"
         connectionString="Server=localhost;Database=database;Uid=User;Pwd=Pswd;"
         providerName="MySql.Data.MySqlClient" />
</connectionStrings>

You also need to add another section to your app.config so that the .NET framework knows about the MySql.Data provider:

<system.data>
    <DbProviderFactories>
        <remove invariant="MySql.Data.MySqlClient" />
        <add name="MySQL Data Provider"
             invariant="MySql.Data.MySqlClient"
             description="ADO.Net driver for MySQL"
             type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
</system.data>

Make sure that the version specified matches the version you have installed or you will get an exception thrown by the .NET runtime at startup when it tries to resolve the assembly.

Then finally, in you application startup, you need to call the overload method for ForConnection so that you can specify the MySqlDialect:

var sessionFactory = Configure
    .Fluently()
    .ForConnection(connectionName: "MySQLTest", sqlDialect: "MicroLite.Dialect.MySqlDialect")
    .CreateSessionFactory();

This article was written for version 3.0.0 of the MicroLite framework.

Update

As of MicroLite 4.0.1, use the ForMySqlConnection method instead:

var sessionFactory = Configure
    .Fluently()
    .ForMySqlConnection("MySQLTest")
    .CreateSessionFactory();

Convention Based Mapping

One of the new features in MicroLite 3.0 is the convention based mapping which allows you to map classes to tables following a set of conventions. MicroLite still defaults to the existing attribute based mapping which allows you to be more explicit, however if you can follow the conventions and the limitations are not a problem, it saves on adding attributes to each class and property.

To configure MicroLite to use it, simply load the extension which is bundled in the main MicroLite assembly:

Configure
    .Extensions() // If used, load any logging extension first.
    .WithConventionBasedMapping(new ConventionMappingSettings
    {
        IdentifierStrategy = IdentifierStrategy.DbGenerated, // default is DbGenerated if not specified.
        UsePluralClassNameForTableName = true // default is true if not specified.
    });

Note that you are required to provide a ConventionMappingSettings, this allows you to configure the settings for the convention based mapping.

The conventions are as follows:

  • Only one identifier strategy can be used across all mapped tables and the chosen strategy is specified in the ConventionMappingSettings.
  • You can choose whether your table names are plural versions of your class name (e.g. if true, class Customer -> table Customers).
  • The class must have a property which is either class name + Id or just Id (e.g. class Customer should have a property called CustomerId or Id).
  • All public properties on a class with a get and set will be mapped.
  • Any enums must be mapped to a column which is enum type + Id (e.g. public CustomerStatus Status { get; set; } will be mapped to column CustomerStatusId.
  • If the database supports schemas, all mapped tables are in the default schema (e.g. dbo for MS SQL).

The conversion of singluar class names to plural table names is reasonably smart, for example it would perform the following conversions (English only in 3.0.0):

Class Name Table Name
Customer Customers
Party Parties
Elf Elves
Man Men
Person People
Child Children
Status Statuses
Mouse Mice
Equipment Equipment (there is no plural of equipment)

If you find a conversion it cannot cater for, you have 2 options:

// Use AddInvariantWord to specify words for which there is no plural version.
MicroLite.Mapping.InflectionService.AddInvariantWord("Equipment");

// Use AddRule to specify or update a regular expression to perform the pluralisation.
MicroLite.Mapping.InflectionService.AddRule(searchPattern: "(.+)", replacementPattern: @"$1s");

The examples shown above are already included in the InflectionService, they are used here as an example and do not need explicitly adding.

If you find any incorrect conversions or missing conversions, please raise an Issue with the details so it can be included in subsequent releases.

There are a number of limitations to using the convention based mapping compared to the standard attribute mapping which are:

  1. All classes must use the same identifier strategy (attribute mapping allows a mixture).
  2. All public properties with a getter and setter will be mapped (attribute mapping is opt-in).
  3. All property names must match the column name with the exception of the identifier property and mapped enum properties (attribute mapping allows any property to be named differently to the column).
  4. All mapped columns except the identifier can be inserted and updated (attribute mapping allows per column configuration of insert or update only columns).

If none of the limitations prevent the conventions from being used in your application or you are creating a new application from scratch and wish to follow the conventions, they can simplify the mapping process.

Note – Since only one mapping convention can be used, you can start on convention mapping and switch to attribute mapping at a later stage if you wish to take advantage of the extra flexibility offered by it.

This article was written for version 3.0.0 of the MicroLite framework.