Monday, December 17, 2018

Accessing Entity Framework context on the background on .NET Core

You got the "Cannot access a disposed object using Entity Framework Core". What should you do?
Photo by Caspar Camille Rubin on Unsplash

You tried to access Entity Framework Core's db context on a background thread in .NET Core and got this error:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
This exception happens because EF Core disposes the connection just after the request to the controller is closed. Indeed that's the right approach and is the default behaviour as we don't want those resources hanging open for much longer. But before going forward, I'd like you to know that most times you don't need or want to access EF Core on a background context. A few good explanations are described here. And, if you need an introduction, I'd also recommend reading Scott Hanselman's introduction on the topic.

However, such an approach sometimes may be necessary. For example, I came across that issue writing a MVP, a proof of concept where a Vue.JS chat room using EF Core communicated with a SignalR Core backend running on Linux. In my opinion MVPs and proofs of concept are the only acceptable use cases for this solution. As always, the default approach should be accessing the service via the injected dependency.

Enough talking. Let's take a look at how to address the problem.

IServiceScopeFactory

The key to doing this is using IServiceScopeFactory. Available on the Microsoft.Extensions.DependencyInjection Nuget package, IServiceScopeFactory provides us a singleton from which we can resolve services trough DI the same way the .NET Core framework does for us.

Microsoft describes it as:
A factory for creating instances of IServiceScope, which is used to create services within a scope. Create an IServiceScope which contains an IServiceProvider used to resolve dependencies from a newly created scope.

The Implementation

The implementation is divided in 3 (three) steps:
  1. Inject the IServiceScopeFactory singleton on your controller
  2. Pass the instance of IServiceScopeFactory to your background task or thread
  3. Resolve the service from the background task

Step 1 - Inject IServiceScopeFactory in your controller

First, you need to inject IServiceScopeFactory in your controller.

Step 2 -  Pass it to your background thread

Then, you have some code that supposedly invokes the bg thread/task. For example:

Step 3 -  Resolve the service from the background task

And finally, when your background thread is run, access the scope and have the framework initialize the EF context for you with:
And because it's a singleton, IServiceScopeFactory won't throw an exception when you try to access it.
at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
at Microsoft.EntityFrameworkCore.DbContext.Add[TEntity](TEntity entity)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Add(TEntity entity)

Conclusion

While you shouldn't use this as a pattern to process background tasks, there are situations where this is necessary. Since the there isn't much documentation around IServiceScopeFactory I thought it was good to document it. Hope it helps!

References

See Also

Monday, December 3, 2018

Simplifying Razor logic with C# Local Functions in ASP.NET Core

How could we use C# Local functions and reduce the boilerplate on our ASP.NET Core pages?

One common requirement developers face is to add custom classes to links dynamically. On this post, I want to show how to do it cleanly in ASP.NET Core by combining two important C# language features: local functions and string interpolation.

Local Functions

Starting with C# 7.0, Microsoft introduced local functions to C#. Local functions are:
private methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from: Methods, Constructors, Property accessors, Event accessors, Anonymous methods, Lambda expressions, Finalizers and Other local functions.

A simple example of how local functions are used is listed below. Note the AppendPathSeparator function: it's what's called a local function in a C# context:
     private static string GetText(string path, string filename)
    {
         var sr = File.OpenText(AppendPathSeparator(path) + filename);
         var text = sr.ReadToEnd();
         return text;    

         // Declare a local function.
         string AppendPathSeparator(string filepath)
         {
            if (! filepath.EndsWith(@"\"))
               filepath += @"\";

            return filepath; 
         }
    }

Now let's look at how we could use local functions in Razor.

Local functions in ASP.NET Core Razor

As we expect, Razor understands local functions. As an example, let's look at a common requirement: adding custom classes on menus depending on the Url the user is in. There are multiple ways to do this. On this post, I want to show how to do it cleanly in Asp.Net Core by using local functions. The solution is done in 3 (three) steps:
  1. Step 1 - Get the controller name
  2. Step 2 - Define the GetClass function to build the css class based on the controller name and link
  3. Step 3 - Use the function in our link;

Step 1 - Get the controller name

In Asp.NET Core, we access the controller name with:
    var controllerName = ((ControllerActionDescriptor)ViewContext.ActionDescriptor).ControllerName;

Step 2 - Define the GetClass function

The next step is to define a local function to toggle the css class based on the controller name. This function gets the controller name as a parameter and appends the class active to the currently set nav-link using string interpolation, another nice feature from C#:
    string GetClass(string controller)
    {
        return $"nav-link { (controllerName == controller ? "active" : "" ) }";
    }

Step 3 - Use the GetClass function in our link

Last step is to use the function in our cshtml templates like:
<a class="@GetClass("Users")" asp-controller="Users" asp-action="Index">Users</a>

Source Code

Here's the full source. See how clean the code got just by using this simple local function and string interpolation in a Bootstrap template layout:

Conclusion

On this post we examined how to use 2 very useful C# language features - local functions and string interpolation - to simplify the development of our Razor templates. Just remember to not violate DRY. If you need the same function elsewhere, move to an extension method so you can re-use it.

References

See Also

About the Author

Bruno Hildenbrand