MicroLite 5.0 – Changes to Logging

In MicroLite 5.0, we have updated the logging API. The information in this post supersedes the information in the Using Logging in Custom Listeners post.

The extension methods which have been removed and the LogManager has been updated so that it will return an empty logger if none is configured. This means that as long as you call MicroLite.Logging.LogManager.GetCurrentClassLog(); you will be returned with an ILog instance.

The ILog interface has been updated with the following properties which allow you to check whether the log is configured at a given level before calling the corresponding log method. This can save on unnecessary calls to resource files and string formatting etc if the log isn’t capturing certain levels of data.

bool IsDebug { get; }
bool IsInfo { get; }
bool IsWarn { get; }
bool IsError { get; }
bool IsFatal { get; }

The ValidationListener in the Using Logging in Custom Listeners post would be updated as follows:

using MicroLite.Logging;

public class ValidationListener : MicroLite.Listeners.Listener
{
    private static ILog log = LogManager.GetCurrentClassLog();

    protected override BeforeInsert(object instance)
    {
        // This ensures that we only pay the cost of calling
        // .GetType() if we want to log the value anyway.
        if (log.IsDebug)
        {
            log.Debug(
                "Validating an {0} before insert",
                instance.GetType().Name);
        }

        ValidateObject(instance);
    }

    protected override BeforeUpdate(object instance)
    {
        // This ensures that we only pay the cost of calling
        // .GetType() if we want to log the value anyway.
        if (log.IsDebug)
        {
            log.Debug(
                "Validating an {0} before update",
                instance.GetType().Name);
        }

        ValidateObject(instance);
    }

    private void ValidateObject(object instance)
    {
        var warnings = Validator.GetWarnings(instance);
        var errors = Validator.GetErrors(instance);

        foreach (var warning in warnings)
        {
            if (log.IsWarn) { log.Warn(warning); }
        }

        foreach (var error in errors)
        {
            if (log.IsError) { log.Error(error); }
        }

        if (warnings.Count > 0 || errors.Count > 0)
        {
            throw new ValidationException(warnings, errors);
        }
    }
}

MicroLite 5.0 – Removal of methods from IListener

In MicroLite 5.0, the mutability of the SqlQuery object has been reduced. This change whilst helping improve the performance of MicroLite and reduce the memory footprint of the framework, does mean that the following methods on IListener can no longer be supported:

void BeforeDelete(object instance, SqlQuery sqlQuery);
void BeforeInsert(object instance, SqlQuery sqlQuery);
void BeforeUpdate(object instance, SqlQuery sqlQuery);

They were originally added in MicroLite 1.2.0 as an extensible point in the pipeline but the purpose of them was never that clear and they were never actually used within the framework itself.

Will this affect you at all? probably not.

  • If you have created a custom listener by inheriting from MicroLite.Listeners.Listener and have not overridden any of the methods mentioned then you won’t have a problem.
  • If you instead implemented MicroLite.Listeners.IListener yourself then if you didn’t actually perform any work in the methods mentioned then you can just delete them and you won’t have a problem.

If you think this change might affect you, move your code into the Before(object instance) method. If you were mutating the SqlQuery, let us know what you were doing and we will let you know the best way to handle it in 5.0.

MicroLite 5.0 – Reduced Mutability of SqlQuery

In MicroLite 5.0, the mutability of the SqlQuery object has been reduced. Once set via the constructor, the command text can now no longer be changed and the arguments cannot be added to or removed from. This allows us to make some performance improvements within the framework since we know the object cannot change.

The class now looks like this:

public sealed class SqlQuery : IEquatable<SqlQuery>
{
    private readonly object[] arguments;
    private readonly string commandText;

    public SqlQuery(string commandText, params object[] arguments)
    {
        this.commandText = commandText;
        this.arguments = arguments ?? new object[0];
    }

    public string CommandText { get { return this.commandText; } }
}

MicroLite 5.0 – Removal of InsertOrUpdate

Another of the changes to the API in MicroLite 5.0 is the removal of the InsertOrUpdate(object) method on ISession.

The reason for the removal is that it only worked correctly if you used the IdentifierStrategy.DbGenerated. In the interest of keeping the API small and not having methods which only work in specific scenarios it has been removed.

If you use the IdentifierStrategy.DbGenerated and wish to keep using this method, you can use the following extension method:

public static void InsertOrUpdate(this ISession session, object instance)
{
    var objectInfo = ObjectInfo.For(instance.GetType());

    if (objectInfo.HasDefaultIdentifierValue(instance))
    {
        session.Insert(instance);
    }
    else
    {
        session.Update(instance);
    }
}

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();

Compiled Help File

Although it isn’t immediately obvious, the NuGet package of MicroLite contains a compiled help file (since release 3.0.3).

You can find it in solution folder\packages\MicroLite.x.x.x\MicroLite.chm it is built from the XML documentation (which also is used by Visual Studio to provide tool tips).

It looks like this:

MicroLite Compiled Help

It is improved with each release an contains example usage for the more commonly used methods.

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.