简体   繁体   English

使用Ninject ADO.NET的DbContext

[英]DbContext with Ninject ADO.NET

I am working on a big project that 80% completed (Some features need to be implemented though).But recently we discovered that the project doesn't allow concurrent requests (I mean multiple users request to same repository). 我正在开发一个80%完成的大项目(有些功能需要实现)。但最近我们发现该项目不允许并发请求(我的意思是多个用户请求到同一个存储库)。 Sometime we get null referece & sometimes "Executed can not open available connection , connection state is closed" etc. Our source code is strongly restricted outside of the world. 有时我们得到null referece&有时“执行无法打开可用连接,连接状态关闭”等。我们的源代码在世界范围内受到严格限制。 Here is some code.Let me know if there is any architectural problem, as architectural guys left company. 这是一些代码。让我知道是否有任何架构问题,因为建筑师离开公司。 It's using ninject 3.0. 它使用的是ninject 3.0。 I already used InRequestScope() for all manager's repositories but no luck 我已经将InRequestScope()用于所有经理的存储库,但没有运气

Update: I am not using any ORM here, I am trying to connect SqlServer through data adapter in my DbContext class 更新:我没有在这里使用任何ORM,我试图通过我的DbContext类中的数据适配器连接SqlServer

public class DbContext
{
  //execute query , nonquery etc using adapter & datatable
  //Example
  var dt=new DataTable();
  _adapter=new _dbfactory.CreateAdapter();
  _adapter.Fill(dt);
  return dt;
}
//MyController
 public class MyController
    {
       private readonly IMyManager_iMyManager;
       public MyController(IMyManager iMyManager){_iMyManager=iMyManager}

       public ActionResult Save()
       {
          _iMyManager.Save()
       }
   }
// My Manager
  public class MyManager:IMyManager
    {
      private readonly  IMyRepository _iMyRepository;
      DbContext _dbContext=new    
                DbContext("someParameter","connectionstring");

     public MyManager
       (
       IMyRepository iMyRepository, DbContext dbContext
       )                    
       {      
        _iMyRepository=iMyRepository;
        _dbContext=dbContext;
       }

  Public DataTable GetDataTable()
  {
    try
    {
      _dbContext.Open();
      _iMyRepository.GetDataTable()
    } 
    catch(Exception ex){}
    finally{_dbContext.Close()}
   }
 }

// here is the repository //这里是存储库

Public class MyRepository:IMyRepository
    {
      public _dbContext;
      public MyRepository(DbContext dbContext)
      {
       _dbContext=dbContext;
      }

      public DataTable GetDataTable()
      { return _dbContext.ExecuteQuery()}
    }

Finally Here is our ninject binding 最后这是我们的ninject绑定

public class NinjectDependencyResolver()
{
   var context=new DbContext("someparameter","connectionStrin");
   kernel.Bind<IMyManager>().To<MyManager>().WithConstructorArgument("_dbContext",context);
   kernel.Bind<IMyRepository >().To<MyRepository >().WithConstructorArgument("_dbContext",context);
}

there can have some typo in my code as I wrote everything in so editor 在我的代码中可能会有一些拼写错误,因为我在编辑器中编写了所有内容

I think you did this too complicated in Ninject Dependency Resolver. 我认为你在Ninject Dependency Resolver中做得太复杂了。

You shouldn't create DbContext with a new keyword. 您不应该使用新关键字创建DbContext。 Instead you should make Ninject to be resolving DbContext in request scope or in thread scope . 相反,您应该让Ninject 在请求范围线程范围内解析DbContext。

To register DbContext you can do it like this: 要注册DbContext,您可以这样做:

kernel.Bind<DbContext>().To<MyDbContext>().WithConstructorArgument("someArgument", "someValue").InRequestScope();
kernel.Bind<IMyManager>().To<MyManager>().InRequestScope();
kernel.Bind<IMyRepository>().To<MyRepository>().InRequestScope();

You don't need to precise the constructor argument to DbContext as DbContext is only once registered in the Ninject. 您不需要精确构造DbContext的构造函数参数,因为DbContext只在Ninject中注册一次。

You can also register DbContext to a DbContextProvider class and there you can add some specific logic to resolve object. 您还可以将DbContext注册到DbContextProvider类,在那里您可以添加一些特定的逻辑来解析对象。

Example: 例:

kernel.Bind<DbContext>().ToProvider<MyDbContextProvider>().InRequestScope();

internal class MyDbContextProvider : Ninject.Activation.IProvider
{
    public object Create(IContext context)
    {
        return new MyDbContext("connectionStringArgument";
    }

    public Type Type { get { return typeof (MyDbContext); } }
}

I hope this helps. 我希望这有帮助。

If you are initializing something in the field level then why would you initialize it again from the constructor? 如果要在字段级别初始化某些内容,那么为什么要从构造函数中再次初始化它?

private readonly  IMyRepository _iMyRepository;    
DbContext _dbContext=new DbContext("someParameter","connectionstring");

public MyManager(IMyRepository iMyRepository, DbContext dbContext)                    
{      
     _iMyRepository=iMyRepository;
     _dbContext=dbContext;
}

This may also be a typo. 这也可能是一个错字。 Either remove the _dbContext initialization from the constructor or delegate the task of initialization to the caller of this class. 从构造函数中删除_dbContext初始化,或将初始化任务委托给此类的调用者。

Multiple initialization can also be the problem. 多次初始化也可能是问题所在。 since you are doing dbcontext initialization both in NinjectDependencyResolver() and MyManager. 因为您在NinjectDependencyResolver()和MyManager中进行dbcontext初始化。 For this you are getting two different exceptions. 为此你得到两个不同的例外。 This is a platform design issue i guess 我想这是一个平台设计问题

You need to remove this initialization in the MyManager since you pass the initialized DbContext via IoC. 您需要在MyManager删除此初始化,因为您通过IoC传递了初始化的DbContext。

 DbContext _dbContext=new    
            DbContext("someParameter","connectionstring");

You also need to remove the finally block in the GetDataTable in the MyManager class since as a rule of thumb, if the object is initialized via IoC, it should be destroyed by IoC as well. 您还需要删除MyManager类中GetDataTable中的finally块,因为根据经验,如果对象是通过IoC初始化的,那么它也应该被IoC破坏。

finally{_dbContext.Close()}

Two problems: 两个问题:

// My Manager
public class MyManager:IMyManager
{
  private readonly  IMyRepository _iMyRepository;
  DbContext _dbContext=new    
            DbContext("someParameter","connectionstring");

 public MyManager
   (
   IMyRepository iMyRepository, DbContext dbContext
   )                    
   {      
    _iMyRepository=iMyRepository;
    _dbContext=dbContext;
   }

The new that is created for the field will be overwritten when the constructor is called. 调用构造函数时,将覆盖为该字段创建的新内容。

public class NinjectDependencyResolver()
{
   var context=new DbContext("someparameter","connectionStrin");
   kernel.Bind<IMyManager>().To<MyManager>().WithConstructorArgument("_dbContext",context);
   kernel.Bind<IMyRepository >().To<MyRepository >().WithConstructorArgument("_dbContext",context);
}

You create the context here once and pass it to each object creation. 您在此处创建一次上下文并将其传递给每个对象创建。 So you are still reusing the context object instead of creating it for each request scope. 因此,您仍在重用上下文对象,而不是为每个请求范围创建它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM