ServiceStack v4.0.15

Individual Products now available

In this release we've added the most requested "non-technical feature" by creating new licenses for individual ServiceStack products which provide much better value when only using one of ServiceStack's stand-alone libraries on their own.

New products available:

Both OrmLite and Redis includes an implicit license for ServiceStack.Text

ServiceStack

  • Upgraded ServiceStack's external dependencies to use latest version on NuGet
  • Modified ServiceStack.RabbitMq to only depend on ServiceStack instead of ServiceStack.Server
  • Added optional fieldName property to ServiceClient PostFileWithRequest
  • Changed exceptions in FileSystem scanning to be logged as warnings, fixes issues with NTFS symbolic links
  • Pass through Thread CurrentCulture when executing a sync request in a new Task
  • Added Evaluator.NamespaceAssemblies to specify alternate default namespace for Assemblies
  • Changed to use OrdinalIgnoreCase instead of InvariantCultureIgnoreCase when possible

OrmLite

OrmLite's core Exec functions are now overridable as a Filter

Continuing in efforts to make OrmLite more introspectable and configurable, OrmLite's core Exec functions have been re-factored out into a substitutable Exec Filter.

This now makes it possible to inject a custom managed exec function where you can inject your own behavior, tracing, profiling, etc.

It comes in useful for situations when you want to use SqlServer in production but use an in-memory Sqlite database in tests and you want to emulate any missing SQL Server Stored Procedures in code:

public class MockStoredProcExecFilter : OrmLiteExecFilter
{
    public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
    {
        try
        {
            return base.Exec(dbConn, filter);
        }
        catch (Exception ex)
        {
            if (dbConn.GetLastSql() == "exec sp_name @firstName, @age")
                return (T)(object)new Person { FirstName = "Mocked" };
            throw;
        }
    }
}

OrmLiteConfig.ExecFilter = new MockStoredProcExecFilter();

using (var db = OpenDbConnection())
{
    var person = db.SqlScalar<Person>("exec sp_name @firstName, @age",
        new { firstName = "aName", age = 1 });

    person.FirstName.Print(); //Mocked
}

Or if you want to do things like executing each operation multiple times, e.g:

public class ReplayOrmLiteExecFilter : OrmLiteExecFilter
{
    public int ReplayTimes { get; set; }

    public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
    {
        var holdProvider = OrmLiteConfig.DialectProvider;
        var dbCmd = CreateCommand(dbConn);
        try
        {
            var ret = default(T);
            for (var i = 0; i < ReplayTimes; i++)
            {
                ret = filter(dbCmd);
            }
            return ret;
        }
        finally
        {
            DisposeCommand(dbCmd);
            OrmLiteConfig.DialectProvider = holdProvider;
        }
    }
}

OrmLiteConfig.ExecFilter = new ReplayOrmLiteExecFilter { ReplayTimes = 3 };

using (var db = OpenDbConnection())
{
    db.DropAndCreateTable<PocoTable>();
    db.Insert(new PocoTable { Name = "Multiplicity" });

    var rowsInserted = db.Count<PocoTable>(q => q.Name == "Multiplicity"); //3
}

Other improvements

  • Added SqlVerifyFragment string extension to verify sql fragments where free-text is allowed in SqlExpression APIs
  • Change MySql to create TimeSpan's column as INT to store ticks

Redis

  • Add new Increment by double and long methods to Redis Client

Text

New Signed NuGet Packages