Notes from Daily Encounters with Technology RSS 2.0
 
# Tuesday, April 22, 2014

Let’s take a look at the following code snippet (for those of you who don’t recognize the API, it’s Sqlite MvvmCross plugin, a slightly modified fork of sqlite-net):

using (var connection = new MvxWpfSqLiteConnectionFactory().Create(_filename))
{
  connection.Execute(
    "CREATE TABLE [MyTable] ([Id] INTEGER NOT NULL PRIMARY KEY);" + 
    "INSERT INTO [MyTable] ([Id]) VALUES (1);");

  var count = connection.ExecuteScalar<int>(
    "SELECT COUNT(*) FROM [MyTable];");

  Console.Write(count);
}

What do you think, the result is? 1? Well, actually it’s 0. And no exception is thrown, in case you were wondering. You can try it out yourself, if you don’t believe me.

This got me curious and I took a closer a look at the sqlite-net code. This is SQLiteConnection.Execute implementation:

public int Execute(string query, params object[] args)
{
  var cmd = CreateCommand(query, args);

  if (TimeExecution)
  {
    if (_sw == null)
    {
      _sw = new Stopwatch();
    }
    _sw.Reset();
    _sw.Start();
  }

  var r = cmd.ExecuteNonQuery();

  if (TimeExecution)
  {
    _sw.Stop();
    _elapsedMilliseconds += _sw.ElapsedMilliseconds;
    Debug.WriteLine(string.Format("...");
  }

  return r;
}

The interesting stuff is in SQLiteCommand.ExecuteNonQuery:

public int ExecuteNonQuery()
{
  if (_conn.Trace)
  {
    Debug.WriteLine("Executing: " + this);
  }

  var r = SQLite3.Result.OK;
  var stmt = Prepare();
  r = SQLite3.Step(stmt);
  Finalize(stmt);
  if (r == SQLite3.Result.Done)
  {
    int rowsAffected = SQLite3.Changes(_conn.Handle);
    return rowsAffected;
  }
  else if (r == SQLite3.Result.Error)
  {
    string msg = SQLite3.GetErrmsg(_conn.Handle);
    throw SQLiteException.New(r, msg);
  }
  else
  {
    throw SQLiteException.New(r, r.ToString());
  }
}

And also in SQLiteCommand.Prepare:

Sqlite3Statement Prepare()
{
  var stmt = SQLite3.Prepare2(_conn.Handle, CommandText);
  BindAll(stmt);
  return stmt;
}

All of the code correctly checks the result codes and throws exceptions accordingly.

Although I haven’t posted all relevant code here, I did review it, and the real origin of this behavior is elsewhere - in the native sqlite3.dll sqlite3_prepare_v2 method. Here’s the relevant part of the documentation: “These routines only compile the first statement in zSql, so *pzTail is left pointing to what remains uncompiled.”

Since sqlite-net doesn’t do anything with the uncompiled tail, only the first statement in the command is actually executed. The remainder is silently ignored. In most cases you won’t notice that when using sqlite-net. You will either use its micro ORM layer or execute individual statements. The only common exception that comes to mind, is trying to execute DLL or migration scripts which are typically multi statement batches.

To handle such cases, you will need to split the batches into single statements. Here’s a quick sample of the idea:

var statements = script.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var statement in statements)
{
  connection.Execute(statement);
}

Don’t use this code in production, though. It will only work as long as you don’t have any semicolons inside your statements. If the batches are completely under you control, you might be able ensure that. Otherwise keep in mind that creating a bulletproof tokenizer for splitting batches into statements is not trivial and you’re probably better off fixing sqlite-net to correctly execute all statements in the command. And while you’re at it, create a pull request, so that others will benefit from your fix as well.

Tuesday, April 22, 2014 9:59:49 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | Sqlite
# Thursday, April 10, 2014

On Wednesday I had my only session at the spring NT conference in Bled this year. I was speaking about the new stuff for developers in Windows 8.1 Update. After a short mention of the universal project, I focused on the changes available only to sideloaded enterprise applications.

Given the small amount of time available for preparing the session, I didn’t prepare any examples of my own and used the publicly available ones from Microsoft instead. As always, you can download my slides from SlideShare.

Apart from the links at the end of the slide deck, keep an eye on Harry Pierson’s blog. He had a session on this subject at Build and his blog is currently probably the best source of information about it.

Thursday, April 10, 2014 9:13:38 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | C# | Metro | Windows Store | Downloads | Presentations
# Monday, March 31, 2014

Recently a colleague of mine mentioned that he has just learned about KeyedByTypeCollection, although it has been included with .NET framework since .NET 3.0. I’m writing this post, because I didn’t know about it until that day, either. This leads me to believe that there must be many more developers out there who aren’t aware of this niche class being readily available.

Unlike other generic collections, it provides a simple way of storing objects of multiple different types in a single collection, still being able to retrieve them in a strongly typed manner. Admittedly, it’s not a common requirement, but there are scenarios in which such a functionality is extremely useful and having a class for it in .NET framework is really nice. Let me present two such scenarios that have come up in my daily work lately.

Designing a data access layer usually also means creating a data context or repository service class, which provides access to repositories of different entity types. This could be a typical repository service interface:

public interface IRepositoryService
{
    IRepository<Player> Players { get; }
    IRepository<Game> Games { get; }
    IRepository<Session> Sessions { get; }
    IRepository<Round> Rounds { get; }
}

Instead of having a separate private field for each entity repository, they can all be stored in a KeyedByTypedCollection and retrieved from it in individual properties:

private KeyedByTypeCollection<object> _repositories;

public IRepository<Player> Players
{
    get
    {
        return _repositories.Find<IRepository<Player>>();
    }
}

This makes it really easy to implement a generic method for accessing repositories based on their entity type, alongside the strongly typed properties or even instead of them:

public IRepository<T> GetRepository<T>()
{
    return _repositories.Find<IRepository<T>>();
}

In Workflow Foundation extensions can be used to provide additional functionalities when hosting workflows, either to activities or during the persistence process. The IWorkflowInstanceExtension interface allows individual extensions to return additional extensions, they require to function correctly.

The handling of these extensions can again be internally implemented very elegantly using a KeyedByTypeCollection:

private KeyedByTypeCollection<object> _extensions = new KeyedByTypeCollection<object>
{
    new PersistenceExtension(),
    new ActivityExtension()
};

public IEnumerable<object> GetAdditionalExtensions()
{
    return _extensions;
}

public void UseIndividualExtensions()
{
    var persistenceExtension = _extensions.Find<PersistenceExtension>();
    var activityExtension = _extensions.Find<ActivityExtension>();
}

Both of the above examples could of course just as well be implemented without KeyedByTypeCollection, but it wouldn’t be as elegant and it would require more code. As I often say, know the tools you are using, .NET framework base class library in this case.

Monday, March 31, 2014 5:04:03 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | WF4
# Monday, March 24, 2014

A great side effect of view models being implemented in portable class libraries when using MvvmCross, is the ability to unit test them on any platform, not necessarily the one you are targeting. So even when developing a mobile application, you can test it in full .NET framework and take advantage of all the tooling available there. In my opinion NCrunch test runner and Moq mocking framework are great examples of tools that are not available for mobile platforms but can make testing much more pleasant.

View model unit tests often depend on PropertyChanged events or have to test them. A typical simple view model unit test checking whether data gets loaded correctly on Start, could look like this:

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);

    var handle = new AutoResetEvent(false);
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == "Players")
        {
            handle.Set();
        }
    };
    viewModel.Start();
    Assert.IsTrue(handle.WaitOne(TimeSpan.FromMilliseconds(50)));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

Contrary to what you would expect, the above test fails because the PropertyChanged event is never raised, even though the view model being tested, works correctly.

After taking a look at MvxNotifyPropertyChanged code, it was easy to explain the behavior. RaisePropertyChanged by default marshals PropertyChanged events to the UI thread (see ShouldAlwaysRaiseInpcOnUserInterfaceThread):

public virtual void RaisePropertyChanged(PropertyChangedEventArgs changedArgs)
{
    // check for interception before broadcasting change
    if (InterceptRaisePropertyChanged(changedArgs)
        == MvxInpcInterceptionResult.DoNotRaisePropertyChanged)
        return;

    var raiseAction = new Action(() =>
            {
                var handler = PropertyChanged;

                if (handler != null)
                    handler(this, changedArgs);
            });

    if (ShouldAlwaysRaiseInpcOnUserInterfaceThread())
    {
        // check for subscription before potentially causing a cross-threaded call
        if (PropertyChanged == null)
            return;

        InvokeOnMainThread(raiseAction);
    }
    else
    {
        raiseAction();
    }
}

In unit tests there’s no Dispatcher set, causing InvokeOnMainThread not to raise the event at all:

protected void InvokeOnMainThread(Action action)
{
    if (Dispatcher != null)
        Dispatcher.RequestMainThreadAction(action);
}

Fortunately the problem is really to fix now, with all the information at hand. There’s no need to marshal the events to UI thread in unit tests, therefore the corresponding view model setting can be disabled (notice the call to ShouldAlwaysRaiseInpcOnUserInterfaceThread(false)):

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);
    viewModel.ShouldAlwaysRaiseInpcOnUserInterfaceThread(false);

    var handle = new AutoResetEvent(false);
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == "Players")
        {
            handle.Set();
        }
    };
    viewModel.Start();
    Assert.IsTrue(handle.WaitOne(TimeSpan.FromMilliseconds(50)));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

With this minor modification the unit test succeeds as expected.

There’s still quite a lot of code involved in setting up the handling of PropertyChanged event in the unit test. Since a similar pattern is often required in tests, it can be wrapped in an extension method to make the tests more straightforward and less repetitive:

public static Task WaitPropertyChangedAsync(this MvxViewModel viewModel, string propertyName)
{
    viewModel.ShouldAlwaysRaiseInpcOnUserInterfaceThread(false);

    var task = new Task(() => { });
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == propertyName)
        {
            task.Start();
        }
    };
    return task;
}

Now the unit test can be much simpler and will only contain the code actually relevant to it:

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);
    var propertyChangedTask = viewModel.WaitPropertyChangedAsync("Players");

    viewModel.Start();
    Assert.IsTrue(propertyChangedTask.Wait(50));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

Monday, March 24, 2014 6:37:58 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | MvvmCross | Testing
# Monday, March 17, 2014

Certain aspects of Workflow Foundation are still poorly documented; the persistence framework being one of them. The following snippet is typically used for setting up the instance store:

var instanceStore = new SqlWorkflowInstanceStore(connectionString);
instanceStore.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
var instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;

It’s difficult to find a detailed explanation of what all of this does; and to be honest, usually it’s not necessary. At least not, until you start encountering problems, such as InstanceOwnerException: The execution of an InstancePersistenceCommand was interrupted because the instance owner registration for owner ID '9938cd6d-a9cb-49ad-a492-7c087dcc93af' has become invalid. This error indicates that the in-memory copy of all instances locked by this owner have become stale and should be discarded, along with the InstanceHandles. Typically, this error is best handled by restarting the host.

The error is closely related to the HostLockRenewalPeriod property which defines how long obtained instance handle is valid without being renewed. If you try monitoring the database while an instance store with a valid instance handle is instantiated, you will notice [System.Activities.DurableInstancing].[ExtendLock] being called periodically. This stored procedure is responsible for renewing the handle. If for some reason it fails to be called within the specified HostLockRenewalPeriod, the above mentioned exception will be thrown when attempting to persist a workflow. A typical reason for this would be temporarily inaccessible database due to maintenance or networking problems. It’s not something that happens often, but it’s bound to happen if you have a long living instance store, e.g. in a constantly running workflow host, such as a Windows service.

Fortunately it’s not all that difficult to fix the problem, once you know the cause of it. Before using the instance store you should always check, if the handle is still valid; and renew it, if it’s not:

if (!instanceHandle.IsValid)
{
    instanceHandle = instanceStore.CreateInstanceHandle();
    var view = instanceStore.Execute(instanceHandle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
    instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}

It’s definitely less invasive than the restart of the host, suggested by the error message.

Monday, March 17, 2014 4:31:30 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | C# | WF4
My Book

NuGet 2 Essentials

About Me
Currently Reading

Xamarin Mobile Application Development for Android

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2014, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.