DbContext with Ninject ADO.NET

本小妞迷上赌 提交于 2019-12-08 05:44:03

问题


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). 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. Here is some code.Let me know if there is any architectural problem, as architectural guys left company. It's using ninject 3.0. I already used InRequestScope() for all manager's repositories but no luck

Update: I am not using any ORM here, I am trying to connect SqlServer through data adapter in my DbContext class

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

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


回答1:


I think you did this too complicated in Ninject Dependency Resolver.

You shouldn't create DbContext with a new keyword. Instead you should make Ninject to be resolving DbContext in request scope or in thread scope.

To register DbContext you can do it like this:

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.

You can also register DbContext to a DbContextProvider class and there you can add some specific logic to resolve object.

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.




回答2:


You need to remove this initialization in the MyManager since you pass the initialized DbContext via IoC.

 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.

finally{_dbContext.Close()}



回答3:


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.

Multiple initialization can also be the problem. since you are doing dbcontext initialization both in NinjectDependencyResolver() and MyManager. For this you are getting two different exceptions. This is a platform design issue i guess




回答4:


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.



来源:https://stackoverflow.com/questions/41146873/dbcontext-with-ninject-ado-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!