markjprice / cs10dotnet6

Repository for the Packt Publishing book titled "C# 10 and .NET 6 - Modern Cross-Platform Development" by Mark J. Price
856 stars 373 forks source link

Building User Interfaces Using Blazor Chapter 17 #70

Open TimCrum1 opened 2 years ago

TimCrum1 commented 2 years ago

Chapter 17, Pages 739-742

After finishing the exercise "Getting entities into a component", I ran the service and kept experiencing an Internal Server Error citing Concurrency errors with a thread attempting to access the context before another thread had finished.

After some quick troubleshooting (aka Google => StackOverflow), I learned that apparently there are some internal design issues within Blazor ServerSide where when two or more components within the same page are trying to execute an async call to the context it will throw DbConcurrency exceptions.

Here is the link to the StackOverflow thread: https://stackoverflow.com/questions/59747983/blazor-concurrency-problem-using-entity-framework-core

The solutions (workarounds), given on StackOverflow, are to set the DbContext's Lifetime to Transient (instead of the default of Scoped) to create a new DbContext instance every time it is called upon or to create a static Singleton service that returns a new instance of DbContext.

My solution to the issue was to simply add an AddNorthwindContextTransient() extension method to our NorthwindContextExtensions.cs class that sets the Lifetime of the context to transient.

public static IServiceCollection AddNorthwindContextTransient(
        this IServiceCollection services, string connectionString =
        "Data Source=.;Initial Catalog=Northwind;"
        + "Integrated Security=true;MultipleActiveResultsets=true;")
    {
        services.AddDbContext<NorthwindContext>(options =>
        options.UseSqlServer(connectionString), ServiceLifetime.Transient);

        return services;
    }

Now, this workaround does indeed work but, given I am only in my third year of my Bachelor's of Applied Technology Software Engineering degree and almost at my first-year mark of working as an ASP.NET Core developer, I have always been instructed that having components access different instances of the DbContext can lead to corrupted data.

Is this the best approach to solving this issue or would you recommend another?

TimCrum1 commented 2 years ago

Well, obviously, the best solution is to abstract the context to a service that is injected, thereby alleviating the issue of having more than one context instantiated as the next section of the chapter instructs you to do. I should have known that to be the best implementation given I implement the repository design pattern in all of my ASP.NET Core Web applications using inheritance and generics with a RepoBase class.