Unity, EntityFramework Core and BackgroundWorker

  • Thread starter Thread starter WRBehning
  • Start date Start date
W

WRBehning

Guest
I have the need to launch different implementations of our IBusinessLogic interface an different threads.

This is being designed in .Net Core3.0 as a console application.

I use Unity to deliver the concrete instance of the BusinessLogic, then pass that to a BackgroundWorker. This seems to work as expected.

The problem I am having is that the application exits all threads at a certain point (It is related to EF Core), but no exceptions are thrown, and I can't find any indication as to what the issue is.

When the businesslogic is executed under the same thread - no Backgroundworker -, it all works as exptected.

Any suggestions?

Here is the relevent code :

See the ProcessBusinessLogic method

public class Main : IDisposable
{
private IUnityContainer _container;

public Main()
{
// Get settings from appsettings
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
var configuration = builder.Build();

var connectionString = configuration.GetConnectionString("MyDatabaseConnection");

// Add the Interception extension
_container.AddNewExtension<Interception>();

_container = new UnityContainer();
// Register Logger

// Register Repository
_container.RegisterType<IRepository, MyRepository>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>());

// Register Data Provider
_container.RegisterType<IDataProvider, MyDataProvider>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>()
, new InjectionConstructor(connectionString));

// Register Business Logic
_container.RegisterTypes(AllClasses.FromLoadedAssemblies()
.Where(type => typeof(IBusinessLogic).IsAssignableFrom(type))
.Where(t => !t.IsGenericTypeDefinition)
, WithMappings.FromAllInterfaces
, WithName.TypeName
, WithLifetime.Transient
, c => new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>() }
);

var salesPadRepository = _container.Resolve<IExptSalesPadRepository>();

_loaderProcessList = salesPadRepository.GetLoaderProcesses();
}


public bool ProcessBusinessLogic()
{
foreach (var loaderProcessDto in _loaderProcessList.Where(o => o.BusinessLogic.Equals("XYZ")))
{
var businessLogicName = string.Concat(loaderProcessDto.BusinessLogic, "BusinessLogic");

var businessLogic = _container.Resolve<IBusinessLogic>(businessLogicName);

// When running on BW - EF Core will kill thread - app just quits with no exceptions being thrown
var executeProcessBackgroundWorker = new BackgroundWorker();
executeProcessBackgroundWorker.DoWork += ExecuteProcess_DoWork;
executeProcessBackgroundWorker.RunWorkerCompleted += ExecuteProcess_RunWorkerCompleted;

executeProcessBackgroundWorker.RunWorkerAsync(businessLogic);

// Running on the same thread, all works as exptected
//var dwe = new DoWorkEventArgs(businessLogic);
//ExecuteProcess_DoWork(this, dwe);
}

return true;
}

private void ExecuteProcess_DoWork(object sender, DoWorkEventArgs e)
{
var businessLogic = e.Argument as IBusinessLogic;

// Create the Order Data
businessLogic.CreateLoaderData(@"C:\Temp\InputData.txt");

// Preprocess data
businessLogic.ProcessLoaderData();

// Process the Input Data
businessLogic.ProcessInput();

}

private void ExecuteProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var x = e;
// Just a sanity check at this point
}

}
}


EF Core DataProvider:

See the Create method:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;

using MyRepository.Configurations;

using System;
using System.Linq;
using System.Text;

namespace MyRepository.DataProvider
{
public class MyDataProvider : DbContext, IMyDataProvider
{
public string DataProviderMessage { get; private set; }

public MyDataProvider(string connectionString)
: base(new DbContextOptionsBuilder().UseSqlServer(connectionString).Options)
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new LoaderProcessConfiguration());
}

public new DbSet<TModel> Set<TModel>() where TModel : class
{
ChangeTracker.DetectChanges();
return base.Set<TModel>();
}

public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>();
}

public TModel Create<TModel>() where TModel : class
{
var model = Activator.CreateInstance<TModel>();

var x = Set<TModel>();

// The next line will kill all threads when running under BW worker
x.Add(model);
return model;
}

public EntityEntry GetEntityStates<TModel>(TModel model) where TModel : class
{
var entityState = Entry(model);
return entityState;
}

}
}







Bill Behning

Continue reading...
 
Back
Top