akd
akd

Reputation: 6730

Autofac DI does not work as expected in Console Application

I have a console application that Autofac DI is used to inject data and service layer from web application project.

here is the setup on console application:

public static class ContainerConfig
{

    public static IContainer Configure()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<DbFactory>().As<IDbFactory>();
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();
        builder.RegisterType<Application>().As<IApplication>();
        builder.RegisterType<DataRepository>().As<IDataRepository>();
        builder.RegisterType<DataService>().As<IDataService>();

        return builder.Build();
    }
}

public interface IApplication
{
    void Run();
}

public class Application : IApplication
{
    private readonly IDataService _dataService;


    public Application(IDataService dataService)
    {
        _dataService = dataService;
    }

    public void Run()
    {
        var data = _dataService.GetDataById(1);         
        var task = new TestTask("test");
        data.AddTask(task);
        _dataService.Update(data);
        _dataService.SaveChanges();
    }       
}

main Program class:

class Program
    {
        static void Main(string[] args)
        {
            var container = ContainerConfig.Configure();
            using (var scope = container.BeginLifetimeScope())
            {
                var app = scope.Resolve<IApplication>();
                app.Run();
            }
        }
    }

When the application is run loading the data works fine. However, saving a new entry does not seem to do the work.

However, when I remove DI and use simple class initializing in the Run method as below the save works fine:

        IDbFactory dbFactory = new DbFactory();
        IDataRepository dataRepository = new DataRepository(dbFactory);
        var unitOfWork = new UnitOfWork(dbFactory);
        IDataService service = new DataService(dataRepository, unitOfWork);
        var data = service.GetDataById(1);
        var task = new TestTask("test");
        data.AddTask(task);
        service.Update(data);
        service.SaveChanges();

Am I missing something while I setup the autofac? It seems to access the data fine but when it comes to save it does not save the data. I debugged to see any issue but the program runs fine with no error. How can I debug this sort of issues to find more details?

Updated

    public interface IDataService
{
    void Add(TestTask task);
    void SaveChanges();
}

public class DataService : IDataService
{
    private readonly IDataRepository _dataRepository;
    private readonly IUnitOfWork _unitOfWork;

    public DataService(IDataRepository dataRepository, IUnitOfWork unitOfWork)
    {
        _dataRepository = dataRepository;
        _unitOfWork = unitOfWork;
    }

    public void Add(TestTask task)
    {
        _dataRepository.Add(task);
    }

    public void SaveChanges()
    {
        _unitOfWork.Commit();
    }
}

public class UnitOfWork : IUnitOfWork
{
    private readonly IDbFactory _dbFactory;
    private ApplicationDbContext _dbContext;

    public UnitOfWork(IDbFactory dbFactory)
    {
        this._dbFactory = dbFactory;
    }

    public ApplicationDbContext DbContext => _dbContext ?? (_dbContext = _dbFactory.Init());

    public void Commit()
    {
        DbContext.Commit();
    }
}

Upvotes: 0

Views: 667

Answers (1)

akd
akd

Reputation: 6730

After reading autofac scopes here

I found out that default scope is Instance Per Dependency. Which means that a unique instance will be returned from each request for a service. DbFactory should be for InstancePerLifetimeScope.

So changing configuration below fixes the issue:

    public static class ContainerConfig
{

    public static IContainer Configure()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();
        builder.RegisterType<Application>().As<IApplication>();
        builder.RegisterType<DataRepository>().As<IDataRepository>();
        builder.RegisterType<DataService>().As<IDataService>();

        return builder.Build();
    }
}

Upvotes: 2

Related Questions