asp.net-mvc – 已经处理了DbContext和autofac

我有一个控制器:
private readonly ILogger _logger;    
private readonly IRepository _repository;

public HomeController(ILogger logger,IRepository repository)
{
   _logger = logger;
   _repository = repository;
}

这是存储库:

public class EfRepository : IRepository
{
    // ...methods for add,delete,update entities
    // ....

    public void dispose()
    {
         if (this._context != null)
         {
             this._context.SaveChanges();
             (this._context as Idisposable).dispose();
             this._context = null;
         }
    }
}

最后,IoC中的注册类型:

_builder.RegisterType<Logger>().As<ILogger>();
_builder.RegisterType<EfRepository>().As<IRepository>().WithParameter("context",new PcpContext());

当我运行应用程序时,我收到此错误

The operation cannot be completed because the DbContext has been
disposed.

我试着像这样改变注册EfRepository:

_builder.RegisterType<EfRepository>()
   .As<IRepository>()
   .WithParameter("context",new PcpContext()).InstancePerLifetimeScope();

在这种情况下,第一个请求完成,但在尝试打开其他页面时,我再次收到错误.哪里有问题?

解决方法

使用WithParameter方法时,参数实例对于每个已解析的对象都是相同的.因此,使用.WithParameter(“context”,new PcpContext()),您可以有效地为任何已解析的IRepository实例使用PcpContext类的相同实例.

使用当前代码,在处理IRepository实例时,它还将释放该PcpContext实例.然后,任何后续尝试解析IRepository都将接收已处置的PcpContext实例.您需要一种方法在每个Http请求上接收一个新的EF DbContext实例,该请求在请求结束时处理.

一种选择可以是为IRepository注册代码块,以便每次需要解析IRepository时执行代码块:

_builder.Register<IRepository>(c => new EfRepository(new PcpContext()))

一个更好的选择是创建一个新的IDatabaseContext抽象,更新EfRepository,因此它依赖于新的IDatabaseContext抽象而不是PcpContextclass(可能已经是这种情况:)).

IDatabaseContext的实现类将是您的PcpContext类,它必须从EF DbContext继承并可能接收连接字符串作为参数.

public class EfRepository : IRepository
{
    private readonly IDatabaseContext _context;

    public EfRepository(IDatabaseContext context)
    {
        _context = context;
    }

    ...methods for add,update entities

    //There is no longer need for this to be disposable.
    //The disaposable object is the database context,and Autofac will take care of it
    //public void dispose()
}

public interface IDatabaseContext : Idisposable 
{
    ... declare methods for add,update entities
}

public class PcpContext: DbContext,IDatabaseContext 
{
    public EntityFrameworkContext(string connectionString)
        : base(connectionString)
    {
    }

    ...methods exposing EF for add,update entities

    //No need to implement Idisposable as we inherit from DbContext 
    //that already implements it and we don´t introduce new resources that should be disposed of
}

使用IoC容器并将生命周期管理负担留给他们的想法变得更好.现在,您的Repository类不需要是一次性的,也不需要管理和处理其IDatabaseContext依赖项. Autofac将跟踪上下文实例并在适当时处理它.

出于同样的原因,您可能希望将InstancePerLifetimeScope与数据库上下文相关性一起使用.这意味着在同一个Http请求中为每个存储库实例共享相同的EF上下文,并在请求结束时进行处理.

_builder.RegisterType<EfRepository>()
   .As<IRepository>();

_builder.RegisterType<PcpContext>()
   .As<IDatabaseContext>()
   .WithParameter("connectionString","NameOfConnStringInWebConfig")
   .InstancePerLifetimeScope();

相关文章

这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识...
Some samples are below for ASP.Net web form controls:(fr...
问题描述: 对于未定义为 System.String 的列,唯一有效的值...
最近用到了CalendarExtender,结果不知道为什么发生了错位,...
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence cha...