Я работаю над большим проектом, который завершил 80% (некоторые функции должны быть реализованы, хотя). Но недавно мы обнаружили, что проект не разрешает одновременные запросы (я имею в виду, что несколько пользователей запрашивают один и тот же репозиторий). Иногда мы получаем null referece, и иногда "Executed не может открыть доступное соединение, состояние соединения закрыто" и т.д. Наш исходный код сильно ограничен за пределами мира. Вот какой-то код. Сообщите мне, есть ли какая-либо архитектурная проблема, поскольку архитектурные ребята покинули компанию. Он использует ninject 3.0. Я уже использовал InRequestScope() для всех репозиториев менеджеров, но не повезло
Обновление: я не использую ORM здесь, я пытаюсь подключить SqlServer через адаптер данных в своем классе DbContext
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()}
}
}
//здесь находится репозиторий
Public class MyRepository:IMyRepository
{
public _dbContext;
public MyRepository(DbContext dbContext)
{
_dbContext=dbContext;
}
public DataTable GetDataTable()
{ return _dbContext.ExecuteQuery()}
}
Наконец, вот наша привязка к 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);
}
в моем коде может быть некоторая опечатка, поскольку я написал все в таком редакторе
Я думаю, вы сделали это слишком сложно в Ninject Dependency Resolver.
Вы не должны создавать DbContext с новым ключевым словом. Вместо этого вы должны сделать Ninject для разрешения DbContext в области запроса или в области потока.
Чтобы зарегистрировать DbContext, вы можете сделать это следующим образом:
kernel.Bind<DbContext>().To<MyDbContext>().WithConstructorArgument("someArgument", "someValue").InRequestScope();
kernel.Bind<IMyManager>().To<MyManager>().InRequestScope();
kernel.Bind<IMyRepository>().To<MyRepository>().InRequestScope();
Вам не нужно уточнять аргумент конструктора DbContext, поскольку DbContext регистрируется только один раз в Ninject.
Вы также можете зарегистрировать DbContext в классе DbContextProvider, и там вы можете добавить определенную логику для разрешения объекта.
Пример:
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); } }
}
Надеюсь, это поможет.
Две проблемы:
// 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 class NinjectDependencyResolver()
{
var context=new DbContext("someparameter","connectionStrin");
kernel.Bind<IMyManager>().To<MyManager>().WithConstructorArgument("_dbContext",context);
kernel.Bind<IMyRepository >().To<MyRepository >().WithConstructorArgument("_dbContext",context);
}
Вы создаете контекст здесь один раз и передаете его каждому созданию объекта. Таким образом, вы все еще повторно используете объект контекста, а не создаете его для каждой области запроса.
Вам нужно удалить эту инициализацию в MyManager
поскольку вы передаете инициализированный DbContext через IoC.
DbContext _dbContext=new
DbContext("someParameter","connectionstring");
Кроме того, необходимо удалить finally
блокировать в GetDataTable в классе MyManager, поскольку, как правило, если объект инициализируется через IoC, он должен быть уничтожен IoC, а также.
finally{_dbContext.Close()}
Если вы инициализируете что-то на полевом уровне, то зачем вам инициализировать его снова из конструктора?
private readonly IMyRepository _iMyRepository;
DbContext _dbContext=new DbContext("someParameter","connectionstring");
public MyManager(IMyRepository iMyRepository, DbContext dbContext)
{
_iMyRepository=iMyRepository;
_dbContext=dbContext;
}
Это также может быть опечаткой. Удалите инициализацию _dbContext из конструктора или делегируйте задачу инициализации вызывающему классу этого класса.
Проблема с множественной инициализацией. поскольку вы выполняете инициализацию dbcontext как в NinjectDependencyResolver(), так и в MyManager. Для этого вы получаете два разных исключения. Это проблема с дизайном платформы, я думаю