【问题标题】:How to inject a parameter constructor into Repository constructor using Ninject?如何使用 Ninject 将参数构造函数注入 Repository 构造函数?
【发布时间】:2018-03-27 23:23:55
【问题描述】:

我正在尝试通过在运行时传递连接字符串来创建 DBContect 对象。 以下是我的 NiNject Repository 实现的结构。

public class HomeController : ApiController
{
    MyService _service{ get; set; }

    public HomeController(MyService service)
    {
        _service= service;
    }
}

public class MyService 
{
    IRepository _repo { get; set; }

    public MyService(IRepository repo)
    {
        _repo = repo;
    }
}

存储库实现如下:

public interface IRepository
{
    TenantDbContext _db { get; set; }
    void Add<T>(T entity) where T : class;
    void Delete<T>(int id) where T : class;
    T Find<T>(int id) where T : class;
    IQueryable<T> Query<T>() where T : class;
    void SaveChanges();

    MasterDbContext _db_master { get; set; }
    void Add_Master<T>(T entity) where T : class;
    void Delete_Master<T>(int id) where T : class;
    T Find_Master<T>(int id) where T : class;
    IQueryable<T> Query_Master<T>() where T : class;
    void SaveChanges_Master();
}

public class Repository : IRepository
{
    public TenantDbContext _db { get; set; }
    public MasterDbContext _db_master { get; set; }

    public Repository(TenantDbContext db)
    {
        _db = db;
    }
    public Repository(MasterDbContext db_master)
    {
        _db_master = db_master;
    }
    public IQueryable<T> Query<T>() where T : class
    {
        return _db.Set<T>().AsQueryable();
    }
    public IQueryable<T> Query_Master<T>() where T : class
    {
        return _db_master.Set<T>().AsQueryable();
    }
//.....Rest of the implemetation
}

这里是我的 TenantDBContext 类,它接受一个参数作为数据库字符串。 无默认构造函数

 public class TenantDbContext : DbContext
{
    public TenantDbContext(string connString)
        : base(connString)
    {
        //Configuration.AutoDetectChangesEnabled = true;
        //Configuration.LazyLoadingEnabled = false;
        //Configuration.ProxyCreationEnabled = false; //change tracking 
    }

    public static TenantDbContext Create(string DbString)
    {
        // Some logic to get the tenant database string. 
        // Presently i am just passing it hard coded as follows.

        return new TenantDbContext(DbString);
    }
}
public class MasterDbContext : IdentityDbContext<ApplicationUser>
{
    public MasterDbContext() : base("MasterDBConnection", throwIfV1Schema: false)
    {
       // dbmigration.AutomaticMigrationsEnabled = true;
        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = false;
    }
    public static MasterDbContext Create()
    {
        return new MasterDbContext();
    }

    //public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public DbSet<Tenant> Tenants { get; set; }
    public DbSet<TenantUserMap> TenantUserMaps { get; set; } }

最后,我在 NinjectWebCommons.cs 中的 RegisterServices 如下所示: 每个租户都有其不同的数据库。我们从每个请求的访问令牌中获取租户名称并缓存该请求的租户对象,以便我们可以传递正确的租户数据库字符串,以便对请求的租户数据库执行操作。

在 sn-p 下面,我们从当前请求缓存中获取租户对象,这将为我们提供所请求客户端的租户数据库字符串。

 public Tenant Tenant
    {
        get
        {
            object multiTenant;
            if (!HttpContext.Current.GetOwinContext().Environment.TryGetValue("MultiTenant", out multiTenant))
            {
                throw new ApplicationException("Could Not Find Tenant");
            }
            return (Tenant)multiTenant;
        }
    }

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IRepository>().To<Repository>();
        kernel.Bind<TenantDbContext>().ToMethod(_ => 
        TenantDbContext.Create(Tenant.DBString)); 
        kernel.Bind<MasterDbContext>().ToMethod(__ => MasterDbContext.Create());
    }   

问题:当我在我的 NinjectWebCommons.cs "kernel.Bind()" 中添加第二个绑定时,我开始收到异常说“未找到默认构造函数”。它根本没有与内核进行两个绑定。请您看看上面的代码并指出我哪里出错了。

感谢您的帮助。提前致谢。

【问题讨论】:

  • 你需要告诉你的容器如何建立你的DbContext。我不使用Ninject,但逻辑就像kernel.[when looking for TenantDbContext].[Use this constructor with this connString]
  • 感谢琼斯波利斯的及时回复。我尝试按照您的建议进行如下操作:
    kernel.Bind&lt;TenantDbContext&gt;().To&lt;TenantDbContext&gt;().WithConstructorArgument("connString", "Data Source = something; Initial Catalog = something; uid = something; pwd = something");
    我知道它错了,只是想检查它是否运行。令人惊讶的是它开始执行但连接字符串没有形成。

标签: c# asp.net-web-api model-view-controller ninject repository-pattern


【解决方案1】:

您可以为数据库上下文添加绑定并指向 Ninject 以使用您的工厂方法:

kernel.Bind<TenantDbContext>().ToMethod(_ => TenantDbContext.Create());

【讨论】:

  • 非常感谢 Peit,它就像一个老板一样工作。你们有这么清晰的概念。 :)
  • 嗨 Peit,我正在尝试添加另一个 ToMethod,但随后 NInject 因未给出默认构造函数错误而停止工作。 kernel.Bind&lt;TenantDbContext&gt;().ToMethod(_ =&gt; TenantDbContext.Create());kernel.Bind&lt;MasterDbContext&gt;().ToMethod(__ =&gt; MasterDbContext.Create());
  • 一次只能使用一个“ToMethod”。如何使用多个“ToMethod”?谢谢!
  • 您可以使用任意数量的.ToMethod(...) 绑定。您共享的代码对我来说看起来不错,所以我敢打赌问题不是由多个绑定引起的。您需要分享更多细节,例如例外情况。
  • 谢谢 Peit,我将与您分享我得到的确切例外情况。我遇到了另一个问题。请您查看原始帖子,如果您对此有解决方案,请告诉我。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多