1
votes

CustomerService is a webservice and it is getting called successfully but I am unable to access SelectCommand in the Any method. I think I am missing something here, could anyone suggest.

public class CustomerService : Service
{
  private readonly IDbConnection _dbConnection; // injected successfully
  public ServiceCommand SelectCommand {get;set;}

  public CustomerService(IDBConnection dbConnection)
  {        
         _dbConnection = dbConnection;            
  }

  public Customer Any(CustomerRequest request)
  {
       //_dbconnection is available           

       //but selectcommand is null here   

       //db operations     

  }
}


[Route("/customers")]
public class CustomerRequest
{
    public string name { get; set; }
}

public class ServiceCommand
{
    public string SQL { get; set; }        
    public CommandType CommandType { get; set; }

    public ServiceCommand()
    {
        CommandType = CommandType.Text;
    }
}

I've initialized the connection by inheriting AppHostBase

  public override void Configure(Container container) {
        container.Register<IDbConnectionFactory>(
          c => new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["default"].ConnectionString,
                                            SqlServerDialect.Provider));

        container.Register<IDbConnection>(c => c.Resolve<IDbConnectionFactory>().OpenDbConnection()).ReusedWithin(ReuseScope.Request);
      }

When I tried to write unit test by setting SelectCommand explicitly, it works. But I am unable to test how it works by not setting the value, I assumed it takes the default value set in the constructor.

 var service = new CustomerService(InMemoryTestDatabase.OpenDbConnection());
 service.SelectCommand = new ServiceCommand() { SQL = "SELECT * FROM customers" };

Edit

IDbConnection in the constructor is working fine but my problem is with SelectCommand which is a public property here. My intention is, if the webservice is called normally I'd hit the actual database by setting query like below in the constructor.

SelectCommand = new ServiceCommand() {Text = "sp_getcustomers"};

But when I test it, I would set it to sqllite database and change my query to table "select * from customers" since sqllite doesn't support sp's. As mentioned unit tests are working fine, but the service is not able to initialize the public properties.

If I initialize a private readonly property same as _dbConnection like below, it works fine but I would like to inject command for the service explicitly.

private readonly IDbConnection _dbConnection;
private readonly ServiceCommand _selectCommand;
public CustomerService(IDBConnection dbConnection)
{
   __dbConnection = dbConnection;
   _selectCommand = new ServiceCommand(){Text = "sp_getCustomers"};
}
1
Are you using a DI container in your application? It may be injecting null value.Ufuk Hacıoğulları
Is there a default constructor(that does not set SelectCommand)? Or is there any other places where SelectCommand may be set to null?alex
Why don't you just use the constructor before using the Any method?Security Hound
SelectCommand = new SeriveCommand(); is a typo, right? You meant SelectCommand = new ServiceCommand();?Roger Rowland
No, DI container is not injecting nullSunny

1 Answers

1
votes

Be sure to include all relevant info and context about your question as this would be impossible to infer without out-of-hand knowledge on how you're using it. E.g. what does your IOC look like?

You're asking for an IDbConnection in your constructor:

public CustomerService(IDBConnection dbConnection)
{
     SelectCommand = new ServiceCommand();
}

But it's very likely you're only registering an IDbConnectionFactory, so there doesn't exist any registered dependency with IDbConnection.

If you inheriting from Service class you've already got the IDbConnectionFactory injected and access to the IDbConnection with the base.Db property:

private IDbConnection db;
public virtual IDbConnection Db
{
    get { return db ?? (db = TryResolve<IDbConnectionFactory>().Open()); }
}

All public properties get injected by the IOC

The reason why SelectCommand property is null is because it's a public property. All of your Services public properties are attempted to be resolved by your Registered dependencies and because you don't have any registered dependencies of type ServiceCommand it is overrided with null. If this was defined in your constructor instead it would've thrown a run-time exception, because it's just a property it's initialized to null.

If you change the visibility of SelectCommand to protected, private, internal or static it wont be attempted to be injected by the IOC.