Monthly Archives: January 2014

MicroLite 5.0

There are some big changes and improvements scheduled for MicroLite 5.0 which is currently in development and you may notice pre-release builds on NuGet.

Feel free to download them and try them out, although be aware that they are still subject to change before they are finally released. Please do not use any pre-release builds for production apps & be aware that there may be changes which are not yet listed on the blog or the wiki.

If you do want to try out MicroLite 5.0 before it’s released, any feedback would be appreciated, either in the comments on the blog or the GitHub issues list (although please keep that to defects or feature requests).

There are a significant number of changes in version 5.0, a large number of those are focused around increasing performance and reducing memory usage (there will be a series of blog posts detailing those over the next few weeks).

As far as the API goes, overall it should be mostly backwards compatible although there are some breaking changes. I won’t cover those in this post as the builds are still at alpha stage and additional changes may occur before 5.0 is released.

Advertisements

Changes to Logging extensions

The MicroLite.Extensions.Log4Net and MicroLite.Extensions.NLog packages have been replaced by MicroLite.Logging.Log4Net and MicroLite.Logging.NLog.

The old packages have been updated to simply act as a redirect to the new ones so you shouldn’t be impacted by this change at all. However it would be worth while uninstalling the old package and installing the new one manually.

The old packages are still listed (but hidden) so things like Package Restore will still work for you.

The main reason for doing this is to get the logging extensions on a cleaner versioning and release process – the early builds were done before I fully understood the way nuget package dependencies worked therefore we ended up with new builds when we didn’t actually need them.

In future, the packages will only be updated if there are breaking changes in MicroLite, Log4Net or NLog that they need to cater for.

MicroLite Comparison Feedback pt2

Following on from yesterdays post, I wanted to address this comment separately:

“PetaPoco just “feels” simpler to use and less like the clunky Spring/Hibernate syntax I wanted to avoid. But it doesn’t appear to be actively maintained. Then again, there are 500+ hits on Stackoverflow (always a useful measure 😉 ) for PetaPoco, and 6 for MicroLite.”

Ignoring the configuration element to MicroLite which we discussed in yesterdays post, how does it differ getting our database access?

// MicroLite
using (var session = sessionFactory.OpenSession())
{
    ...
}

// PetaPoco
using (var database = new Database("sqlite"))
{
    ...
}

OK, they’re pretty similar. How about using a transaction?

// MicroLite
using (var transaction = session.BeginTransaction())
{
    ...
    transaction.Complete();
}

// PetaPoco
using (var transaction = database.GetTransaction())
{
    ...
    transaction.Complete();
}

Again, almost identical.

Something that MicroLite offers is the option to override the IsolationLevel which by default is ReadCommitted.

// MicroLite
session.BeginTransaction(IsolationLevel.Serializable))

PetaPoco provides an alternative method for managing the transaction although I’m not sure what the difference is between them or why you need 2 ways to do the same thing.

// PetaPoco method 2
database.BeginTransaction();
...
database.CompleteTransaction();

Overall so far things are pretty similar. So how about the common methods used in most applications?

MicroLite 4.0.1
Delete Delete(object instance)
Delete(Type type, object identifier)
Insert Insert(object instance)
InsertOrUpdate(object instance)
Select (single) Single<T>(object identifier)
Single<T>(SqlQuery sqlQuery)
Select (many) Fetch<T>(SqlQuery sqlQuery)
Paged<T>(SqlQuery sqlQuery, PagingOptions pagingOptions)
Projection(SqlQuery sqlQuery)
Update Update(object instance)
InsertOrUpdate(object instance)
PetaPoco 5.0.1
Delete Delete(object poco)
Delete(string tableName, string primaryKeyName, object poco)
Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue)
Delete<T>(object pocoOrPrimaryKey)
Delete<T>(string sql, params object[] args)
Delete<T>(Sql sql)</code
Insert Insert(object poco)
Insert(string tableName, string primaryKeyName, object poco)
Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco)
Save(object poco)
Save(string tableName, string primaryKeyName, object poco)
Select (single) Single<T>(object primaryKey)
Single<T>(string sql, params object[] args)
Single<T>(Sql sql)
SingleOrDefault<T>(object primaryKey)
SingleOrDefault<T>(string sql, params object[] args)
SingleOrDefault<T>(Sql sql)
First<T>(string sql, params object[] args)
First<T>(Sql sql)
FirstOrDefault<T>(string sql, params object[] args)
FirstOrDefault<T>(Sql sql)
Select (many) Fetch<T>(string sql, params object[] args)
Fetch<T>(Sql sql)
Fetch<T>(long page, long itemsPerPage, string sql, params object[] args)
Fetch<T>(long page, long itemsPerPage, Sql sql)
Fetch<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, string sql, params object[] args)
Fetch<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, Sql sql)
Fetch<T1, T2, T3, T4>(string sql, params object[] args)
Fetch<T1, T2, T3, T4>(Sql sql)
Fetch<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, string sql, params object[] args)
Fetch<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, Sql sql)
Fetch<T1, T2, T3>(string sql, params object[] args)
Fetch<T1, T2, T3>(Sql sql)
Fetch<T1, T2, TRet>(Func<T1, T2, TRet> cb, string sql, params object[] args)
Fetch<T1, T2, TRet>(Func<T1, T2, TRet> cb, Sql sql)
Fetch<T1, T2>(string sql, params object[] args)
Fetch<T1, T2>(Sql sql)
Page<T>(long page, long itemsPerPage, string sqlCount, object[] countArgs, string sqlPage, object[] pageArgs)
Page<T>(long page, long itemsPerPage, string sql, params object[] args)
Page<T>(long page, long itemsPerPage, Sql sql)
Page<T>(long page, long itemsPerPage, Sql sqlCount, Sql sqlPage)
Query<T>(string sql, params object[] args)
Query<T>(Sql sql)
Query<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, string sql, params object[] args)
Query<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, Sql sql)
Query<T1, T2, T3, T4>(string sql, params object[] args)
Query<T1, T2, T3, T4>(Sql sql)
Query<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, string sql, params object[] args)
Query<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, Sql sql)
Query<T1, T2, T3>(string sql, params object[] args)
Query<T1, T2, T3>(Sql sql)
Query<T1, T2, TRet>(Func<T1, T2, TRet> cb, string sql, params object[] args)
Query<T1, T2, TRet>(Func<T1, T2, TRet> cb, Sql sql)
Query<T1, T2>(string sql, params object[] args)
Query<T1, T2>(Sql sql)
Query<TRet>(Type[] types, object cb, string sql, params object[] args)
SkipTake<T>(long skip, long take, string sql, params object[] args)
SkipTake<T>(long skip, long take, Sql sql)
Update Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue)
Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue, IEnumerable columns)
Update(string tableName, string primaryKeyName, object poco)
Update(string tableName, string primaryKeyName, object poco, IEnumerable columns)
Update(object poco, IEnumerable columns)
Update(object poco)
Update(object poco, object primaryKeyValue)
Update(object poco, object primaryKeyValue, IEnumerable columns)
Update<T>(string sql, params object[] args)
Update<T>(Sql sql)
Save(object poco)
Save(string tableName, string primaryKeyName, object poco)

MicroLite has 2 methods for Delete, Insert, Select Single & Update and 3 for Select Many (arguably 2 since Projection has been obsoleted in favour of using Fetch<dynamic>).

PetaPoco however has 6 for Delete, 5 for Insert, 10 for Select Single, 12 for Update and a ridiculous 37 for Select Many! Maybe not simpler after all.

MicroLite Comparison Feedback

I stumbled across this Micro ORM Comparison and thought I’d post my thoughts.

The part about requiring more setup code is correct, whilst PetaPoco can be created as var db = new PetaPoco.Database("sqlite");. MicroLite requires you to create a session factory which in turn will create sessions.

Now it’s a fair point that we do need to write a few more lines of code to set up MicroLite, but it’s worth reviewing why that is. Firstly, you only need to write the setup code once in your application where the application actually starts (Global.asax/ App_Start for a web app or Program.cs for a windows forms/console app etc). Secondly, the actual MicroLite session is exposed via the ISession interface, this allows you to write nicely decoupled and testable code which is using MicroLite – something most other Micro ORM frameworks don’t enable.

The points about the convention based mapping are also worth considering – Yes the default conventions do expect the column names to match the property names (in casing as well). In the example, the foo class is cased using camelCasing rather than PascalCasing for the type name and properties which isn’t the capitalization convention used by the .NET framework. However it’s not so good if users feel that MicroLite is too rigid in this sense in preventing you from defining your own convention or tweaking the default convention as necessary.

The post was based on MicroLite 3.1.1, but it is worth mentioning that in MicroLite 4.0 we introduced much greater control over the conventions so for the example you could leave the database and class casing as camelCase and then override the IsIdentifier method in the convention settings:

new ConventionMappingSettings
{
    // Provide a custom method which checks if the property name
    // is lower case 'id'.
    IsIdentifier = (PropertyInfo propertyInfo) => 
    { 
        return propertyInfo.Name == “id”; 
    }
}

The functionality that MicroLite offers above basic CRUD operations are also worth considering if you are considering Micro ORM frameworks:

  • An API to include additional queries in a single database call.
  • A powerful fluent Sql Builder to build more complex queries at runtime.
  • The ability to Intercept Delete, Insert and Update calls via the IListener interface.
  • The ability to create custom Type converters via the ITypeConverter interface.
  • Custom extensions for ASP.NET MVC and WebAPI.
  • Integration with Log4Net or NLog if you want any log data from MicroLite to be written to your application log and you use either framework (to the flexibility to create your own logging extension)
  • A compiled help file and rich xml documentation for tool tips in Visual Studio.

There’s also the question of performance which I’ll cover in another post.