3

I'm registering a DbContext onto the TinyIoCContainer that's passed into the ConfigureRequestContainer method on the DefaultNancyBootstrapper.

Whilst this works fine, I've noticed that the Dispose method on the context is never called once a request has completed. I'd expect the DbContext to be disposed of after a request to close the connection (we're using SQLite).

Q: Are disposable instances actually disposed at the end of a request within the TinyIoCContainer?

Bootstrapper

protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
    base.ConfigureRequestContainer(container, context);

    container.Register<IContext>((_,__) => 
    {
        // Code here to get connection string
        return new Context(new SQLiteConnection(connString), true);
    });
}

Context

public interface IContext : IDisposable
{
    ...
}

public class Context : DbContext, IContext
{
    ...

    public new void Dispose()
    {
        base.Dispose();  // This never gets called
    }
}

Update

The marked answer was ultimately correct. I basically had to do something like so:

if (string.IsNullOrEmpty(context.Request.UserHostAddress))
{
    container.Register<IContext>((_,__) => null);
}
else
{
    // Get username from request headers
    // Build up SQLite connection string based off username
    var dbContext = new Context(new SQLiteConnection(connString));
    container.Register<IContext>(dbContext);
}
Tom
  • 2,321
  • 2
  • 18
  • 29
  • Why don't you test it? Put in a trace-line into your Dispose method. However, `public new void Dispose()` is not `void IDisposable.Dispose()`. That is what `new` means. – Aron May 05 '17 at 09:29
  • I've tested it by putting a breakpoint on the `base.Dispose` line - it gets called if I use the context within a `using` statement so I figured it would get called after a request too, although I did suspect I may be misusing it! I'll try adding a trace line, thanks. – Tom May 05 '17 at 09:33
  • You really want to replace the work `new` with `override`. – Aron May 05 '17 at 09:39
  • @Aron I can't override Dispose, although I can override `Dispose(bool disposing)`. Either way, the `new` Dispose method still gets fired. I put in a `Debug.WriteLine` and it never gets called, unless I do `container.Resolve().Dispose()` on the `AfterRequest` pipeline. – Tom May 05 '17 at 14:05

2 Answers2

2

I think its because you're using the manual factory registration, it expects you to control lifetime yourself. You probably don't want to be using that anyway, as you are creating a new context every time you ask for one with the code you have there - switch it to an instance registration and you should be ok.

container.Register<IContext>(new Context(new SQLiteConnection(connString), true));
Steven Robbins
  • 26,441
  • 7
  • 76
  • 90
  • We need the factory registration because the username sent in the request header determines which database to use, and unfortunately the headers aren't available the first time the method is called. I would have assumed any registration on the RequestContainer would last the lifetime of the request, but I must have assumed wrong! Just found this https://github.com/grumpydev/TinyIoC/wiki/Registration---lifetimes it mentions an extension which can be used to specify a per request lifetime - I'll give that a go. – Tom May 05 '17 at 10:03
0

Haven't used TinyIoC a lot but this page says that registration per request is different, not sure if that should always be the case.

https://github.com/grumpydev/TinyIoC/wiki/Registration---lifetimes

Alex Paven
  • 5,539
  • 2
  • 21
  • 35