IDbConnectionFactory is null

Hello Experts,

I am not able to understand that why my below mentioned businessObject is not getting proper IDbConnectionFactory instance.

I have also noted that in my service class which is inherited from Service base class is properly getting the IDbConnectionFactory however when the control is reaching to BusinessObject where I want to orchestrate things and business logic there this IDbConnectionFactory is null

Here is the appHost where IDBConnectionString is added as singleton.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ServiceStack;
using ServiceStack.Data;
using ServiceStack.DataAnnotations;
using ServiceStack.OrmLite;
[assembly: HostingStartup(typeof(Realtor.ConfigureDb))]

namespace Realtor
{
    public class ConfigureDb : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder) => builder
            .ConfigureServices((context, services) =>
            {
                services.AddSingleton<IDbConnectionFactory>(new OrmLiteConnectionFactory(
                context.Configuration.GetConnectionString("DefaultConnection"), PostgreSqlDialect.Provider));
                
            })
            .ConfigureAppHost(appHost =>
            {
                // Enable built-in Database Admin UI at /admin-ui/database
                // appHost.Plugins.Add(new AdminDatabaseFeature());

                // This is the piece of code if we need to use multiple databases, such as Multi Tenancy Case
                var logDbConnStr = "ConnectionStrings:LogDbConnection";
                //var constr = appHost.AppSettings.Get<string>(appSettingsKey);
                //var logDbConnString = Convert.ToString(appHost.AppSettings.GetDictionary("ConnectionStrings")["LogDbConnection"]);
                var logDbConnString = appHost.AppSettings.GetString(logDbConnStr);
                var dbFactory = appHost.Container.Resolve<IDbConnectionFactory>() as OrmLiteConnectionFactory;
                if (dbFactory == null) return;
                dbFactory.RegisterConnection("LogDbConnection", logDbConnString, PostgreSqlDialect.Provider);
                //var db = dbFactory.OpenDbConnectionString(logDbConnString);

            });
    }
}

Business Object

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServiceStack;
using ServiceStack.Data;
using ServiceStack.OrmLite;

namespace Realtor.BusinessObjects.Features
{
    public class MainCategoryBo
    {
        public MainCategoryBo() { }
        public IDbConnectionFactory? DbConnectionFactory { get; set; } 
        public bool GetMainCategoires()
        {
            var result = false;

            var mainCategoryData = new Realtor.Data.Dac.MainCategory();

            using (var db = DbConnectionFactory.Open())
            {
                // here DbConnectionFactory is null
            }

            var mainCategoreis = mainCategoryData.GetMainCategories();
            

            return result;
        }
    }
}

Kindly advise…

Where are you registering then resolving MainCategoryBo from the IOC?

It looks like you are missing the resolving of Inversion of Control (IoC) dependencies from the IoC container. This happens automatically for your services (classes that inherit from Service), but it is something you will have to do yourself for custom classes where you control the instantiation of instances.

You could register your MainCategoryBo and use AutoWire method off the Funq container to resolve an instance with the wired up injected dependencies.

Alternatively you could register your MainCategoryBo as an AutoWired dependency as shown in our docs. This would enable you to declare your MainCategoryBo on your service as a property just like IDbConnectionFactory and it will be wired up with its own dependencies. Eg

.ConfigureAppHost(appHost =>
            {
               appHost.Container.RegisterAutoWired<MainCategoryBo>();
            });

// Your service:
public class MyServices : Service
{
    public MainCategoryBo MainCategoryBo { get; set; }
    
    // Existing services
}

If you want to use your MainCategoryBo outside a service, you will need to use container.AutoWire(mainCategoryBoInstnace), this will populate the injected properties so they can be used. Hope that helps.

Experts @layoric / @mythz,

@mythz, yes I missed the IOC part which you have pointed out perfectly.

@layoric as guided I have followed your instructions to register the dependency using AutoWire feature and it worked.

@layoric I still need to understand this further that how can I pass the instance. Do I need to create the instance of MainCategoryBo first in AppHost and then I can set it like this container.AutoWire(mainCategoryBoInstnace)

Thank you so much both of you.

Best regards

Right, if you are in a Service you don’t need to do this, but if you are in another context of your application, like custom background jobs for example, you can create a new instance of your MainCategoryBo and initialize it using container.AutoWire which will resolve matching IoC by registered type, populating your property injected dependencies. Here is a simple example:

var myObject = new MainCategoryBo();
HostContext.Container.AutoWire(myObject);

Using it this way will generally be the exception not the rule as libraries and frameworks (like ServiceStack) that integrate with ASPNET will support the built in dependency injection. Microsoft docs have some good resources on dependency injection (DI) if you are looking at different ways of incorporating it into your application, either via ServiceStack or directly with ASPNET.

@layoric thank you so much for providing the detailed response and helping me to understand the concept. You are a star :slightly_smiling_face:

1 Like