We are using InstancePerLifetimeScope
for Database . But in some case we need a new db connection.
Our autofac registration is
builder.RegisterType<Npgsql.NpgsqlConnection> ()
As<IDbConnection> ()
.WithParameter ("connectionString", constr)
.InstancePerLifetimeScope ();
// for NewDb Connection
builder.RegisterType<Npgsql.NpgsqlConnection> ()
.As<IDpNewDb> ()
.WithParameter ("connectionString", constr)
.InstancePerRequest ();
Code for IDpNewDb is
public interface IDpNewDb : IDbConnection { }
We are getting a error while running this code
An exception of type 'System.ArgumentException' occurred in Autofac.dll but was not handled in user code: 'The type 'Npgsql.NpgsqlConnection' is not assignable to service 'xxxx.Core.Data.IDpNewDb'.'
Any idea ?
Edit : Below the code for a cut-down version of the app
My Startup Class
public class Startup {
public Startup (IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices (IServiceCollection services) {
services.AddMvc ().SetCompatibilityVersion (CompatibilityVersion.Version_2_2);
ConfigureAutofac (services);
}
internal static AutofacServiceProvider ConfigureAutofac (IServiceCollection services) {
var containerBuilder = new ContainerBuilder ();
containerBuilder.RegisterModule<DefaultModule> ();
containerBuilder.Populate (services);
var container = containerBuilder.Build ();
var srv = new AutofacServiceProvider (container);
return srv;
}
public void Configure (IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment ()) {
app.UseDeveloperExceptionPage ();
} else {
app.UseHsts ();
}
app.UseHttpsRedirection ();
app.UseMvc ();
}
}
Autofac Module
internal class DefaultModule : Autofac.Module {
public void init (ContainerBuilder builder) {
Load (builder);
}
protected override void Load (ContainerBuilder builder) {
builder.RegisterType<Npgsql.NpgsqlConnection> ()
.As<IDbConnection> ()
.WithParameter ("connectionString", "Server=localhost;Database=DBName;User Id=postgres;password=*******;Application Name=myapp;")
.InstancePerLifetimeScope ();
builder.RegisterType<Npgsql.NpgsqlConnection> ()
.As<IDbNewDb> ()
.WithParameter ("connectionString", "Server=localhost;Database=DBName;User Id=postgres;password=******;Application Name=myapp;")
.InstancePerRequest ();
}
}
interfaces.cs
namespace autofac_issue {
public interface IDbNewDb : IDbConnection { };
}
Finally, Controller
namespace autofac_issue.Controllers {
[Route ("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase {
// GET api/values
public ValuesController (IDbNewDb dbnew, IDbConnection db) {
}
}
}
The following line won't work
builder.RegisterType<Npgsql.NpgsqlConnection> ()
.As<IDpNewDb> ()
NpgsqlConnection
does not implement IDpNewDb
. You will have a similar error even using pure C#.
If you want a new instance of IDbConnection
you can use Owned
combined with Func<>
which will act like a mini scope and you will have a new instance whenever you want.
public class X {
public X(Func<Owned<IDbConnection>> dbConnectionFactory){
this._dbConnectionFactory = dbConnectionFactory;
}
private readonly Func<Owned<IDbConnection>> _dbConnectionFactory;
public void Do(){
// will create a new instance each time you call the factory
using(Owned<IDbConnection> ownedDbConnection = this._dbConnectionFactory()){
IDbConnection dbConnection = ownedDbConnection.Value;
}
}
}
See Combining Owned
with Func
from the Autofac documentation for more information.