Tag Archives: Configuration

MicroLite 6.0 – Dynamic Connection Strings

Prior to MicroLite 6.0, in order to create a session factory you had to specify the connection name as defined in the connection strings section of your application configuration. This is generally a good idea as the connection string is a configuration value which should not be baked into the code as you would need a different value if you have separate Dev/Test/Production environments.

We did have a request from a MicroLite user to be able to specify the connection string at runtime as there is a requirement for that in his application so we have added functionality for doing just that.

The ForConnection methods now have an additional overload:

ForMsSql2005Connection(string connectionName, string connectionString, string providerName)

The reason that the new overload needs a connection name is to still allow support for the MVC and WebApi extensions which are dependent on a named connection to resolve the correct session factory.

The provider name needs to be the same as you would set in the connection string in the application config, this is used by MicroLite to resolve the correct DbProviderFactory.

This gives you two ways to configure a connection in MicroLite 6.0:

Option 1 (the recommended approach for most use cases)

Define the connection string in the application configuration

<connectionStrings>
    <add name="NorthwindDB"
         connectionString="Data Source=localhost;Initial Catalog=Northwind;Persist Security Info=False;Integrated Security=SSPI;"
         providerName="System.Data.SqlClient" />
</connectionStrings>
// Create the session factory for the named connection
var sessionFactory = Configure
        .Fluently()
        .ForMsSql2005Connection("NorthwindDB")
        .CreateSessionFactory();

Option 2 (if you really really need to)

// Create the session factory with the specified name, connection string and provider name
var sessionFactory = Configure
        .Fluently()
        .ForMsSql2005Connection(
               "NorthwindDB",
               "Data Source=localhost;Initial Catalog=Northwind;Persist Security Info=False;Integrated Security=SSPI;",
               "System.Data.SqlClient")
        .CreateSessionFactory();
Advertisements

MicroLite 5.0 – String Handling

In .NET, strings are Unicode, however some databases have specific data types for strings which differentiate between ASCII and Unicode (e.g. in MS SQL Server VarChar being ASCII and NVarChar being Unicode).

If the database makes the distinction and the wrong type is used in a SQL command, it can result in poor performing queries (table scans over index lookups or unnecessary type conversion).

In MicroLite 5.0, the database connection/command handling has been exposed via a ‘database driver’. The new IDbDriver interface defines a HandleStringsAsUnicode property which is set to true by default but allows explicit control over whether strings are sent to the database as ASCII or Unicode (the default).

If you use MS SQL Server and the columns are NVarChar, HandleStringsAsUnicode should be left as true (the default value). If they are VarChar, HandleStringsAsUnicode should be set to false.

For other databases, refer to the documentation and if in doubt, leave it set to true.

If you need to, you can set HandleStringsAsUnicode to false when the session factory is created:

var sessionFactory = Configure.Fluently()
    .ForMsSqlConnection("Connection")
    .CreateSessionFacory();

// Only change this if you are sure you need to.
sessionFactory.DbDriver.HandleStringsAsUnicode = false;

MicroLite 5.0 – Changes to Convention Mapping

In MicroLite 5.0, we are making further enhancements to the convention based mapping which provide even greater flexibility.

Convention Mapping History:

The changes in MicroLite 5.0 are as follows:

ResolveIdentifierStrategy

We have replaced the IdentifierStrategy property with the ResolveIdentifierStrategy method. This means that you no longer have to use the same IdentifierStrategy for every class (or that you can migrate from attribute mapping to convention mapping if this was preventing you from doing so).

By default it will return IdentifierStrategy.DbGenerated but you can override it if you want to specify a different strategy or calculate it based upon the type:

Configure.Extensions().WithConventionBasedMapping(
    new ConventionMappingSettings
    {
        ResolveIdentifierStrategy = (Type type) => 
        {
            if (type == typeof(MySpecialType))
            {
                return IdentifierStrategy.Assigned;
            }

            return IdentifierStrategy.DbGenerated; 
        }
    });

ResolveTableSchema

We have replaced the TableSchema property with the ResolveTableSchema method. This means that you no longer have to use the same schema for every class (or that you can migrate from attribute mapping to convention mapping if this was preventing you from doing so).

By default it will return null but you can override it if you want to specify a specific schema or calculate it based upon the type:

Configure.Extensions().WithConventionBasedMapping(
    new ConventionMappingSettings
    {
        ResolveTableSchema = (Type type) => 
        {
            if (type == typeof(MySpecialType))
            {
                return "MySpecialSchema";
            }

            return "dbo"; 
        }
    });

MicroLite 5.0 – Changes to IdentifierStrategy

One of the changes coming in MicroLite 5.0 is the removal of the IdentifierStrategy options for Guid and GuidComb.

If you currently use either of them, you can maintain the functionality by using the Assigned IdentifierStrategy and creating a custom IListener to set the value.

using System;
using MicroLite.Listeners;
using MicroLite.Mapping;

public class GuidListener : Listener
{
    public override void BeforeInsert(object instance)
    {
        var objectInfo = ObjectInfo.For(instance.GetType());

        if (objectInfo.TableInfo.IdentifierColumn.PropertyInfo.PropertyType == typeof(Guid))
        {
            var identifier = Guid.NewGuid();

            objectInfo.SetIdentifierValue(instance, identifier);
        }
    }
}

If you used the GuidComb strategy, you can find the code to generate the next GUID here and use this line instead:

var identifier = GuidGenerator.CreateComb();

Using SQLite (Updated)

In the Using SQLite post, we covered how to use the SQLite.Data library with MicroLite.

Recently however in version 1.0.91.0, the SQLite team have decided that the nuget package we were recommending adds a dependency on Entity Framework. Fortunately they have also released a separate package System.Data.SQLite.Core which is just the core SQLite.Data with no further dependencies.

The previous instructions should still all be the same, just change to use the System.Data.SQLite.Core package instead.

MicroLite 4.0 – Convention Based Mapping Enhancements

In MicroLite 3.0, we introduced convention based mapping and with MicroLite 4.0 we are changing to make convention based mapping the default. Also, a number of enhancements have been made to allow your conventions to be specified.

The ConventionMappingSettings class now has a number of extra properties which can be configured to define your own conventions. The default values for these are backwards compatible with the conventions defined in MicroLite 3.0.

AllowInsert

The AllowInsert property is a Func<PropertyInfo, bool> which can be used to specify whether a property value can be inserted (the equivalent of setting AllowInsert = false on the ColumnAttribute if you were using attribute mapping). By default, this method will always return true, however if you had an audit property with updated date, you could configure the settings as follows:

Configure.Extensions().WithConventionBasedMapping(
    new ConventionMappingSettings
    {
        AllowInsert = (PropertyInfo propertyInfo) => 
        {
            return propertyInfo.Name != "Updated"; 
        }
    });

AllowUpdate

The AllowUpdate property defines a Func<PropertyInfo, bool> which can be used to specify whether a property value can be updated after it is first inserted (the equivalent of setting AllowUpdate = false on the ColumnAttribute if you were using attribute mapping). By default, this method will always return true, however if you had an audit property with created date which should not be changed, you could configure the settings as follows:

Configure.Extensions().WithConventionBasedMapping(
    new ConventionMappingSettings
    {
        AllowUpdate = (PropertyInfo propertyInfo) => 
        {
            return propertyInfo.Name != "Created"; 
        }
    });

Ignore

The Ignore property defines a Func<PropertyInfo, bool> which can be used to specify whether a property which would ordinarily be mapped should be ignored (the equivalent of not applying a ColumnAttribute if you were using attribute mapping). By default, this method will always return false.

IsIdentifier

The IsIdentifier property defines a Func<PropertyInfo, bool> which can be used to specify whether a property is the property mapped to the identifier column in the database table. By default, this method will return true if the property name is Id or {ClassName} + Id.

ResolveColumnName

The ResolveColumnName property defines a Func<PropertyInfo, string> which can be used to resolve the name of the column a property is mapped to. By default, the property name will be used unless the property is an enum in which case {EnumType} + Id will be used.

Example public string Forename would resolve to Forename whereas public CustomerStatus CustomerStatus would resolve to CustomerStatusId.

ResolveIdentifierColumnName

The ResolveIdentifierColumnName property defines a Func<PropertyInfo, string> which can be used to resolve the name of the column the identifier property is mapped to. This function will only be invoked if the IsIdentifier function returns true. By default, this will return the property name.

Example public int Id would resolve to Id so the expected column name in the database would be Id.

If your database schema defines the identifier column as TableName + Id (e.g. CustomerId) but in your code you want to use public int Id, you could implement the method as follows:

Configure.Extensions().WithConventionBasedMapping(
    new ConventionMappingSettings
    {
        ResolveIdentifierColumnName = (PropertyInfo propertyInfo) => 
        {
            return propertyInfo.DeclaringType.Name + "Id"; 
        }
    });

Unit Testing when using the Convention Based Mapping

If you are using the new Convention Based Mapping introduced in MicroLite 3.0 and want to unit test code which uses the SqlBuilder, you will need to ensure that the convention extension is loaded before the tests are run.

The reason for this is that the SqlBuilder reads the ObjectInfo for the type being queried to append the column names and ObjectInfo uses the mapping convention to interrogate the type information. Since the default mapping convention is the AttributeMappingConvention, it will be called instead of the ConventionMappingConvention.

The recommended approach here is to move the configuration of MicroLite extensions into a separate class:

public static class MicroLiteConfig
{
    public static void ConfigureExtensions()
    {
        Configure
            .Extensions()
            .WithNLog() // If used, always load the logging extension first.
            .WithConventionBasedMapping(new ConventionMappingSettings
            {
                IdentifierStrategy = IdentifierStrategy.DbGenerated,
                UsePluralClassNameForTableName = true
            })
            .WithMvc();

        // Register any listeners etc.
    }
}

You can then call MicroLiteConfig.ConfigureExtensions() in your test setup method.

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