gpt4 book ai didi

asp.net-mvc - DbContext 已被释放并且 autofac

转载 作者:行者123 更新时间:2023-12-02 12:19:47 30 4
gpt4 key购买 nike

我有一个 Controller :

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()),您可以有效地将 PcpContext 类的相同实例用于任何已解析的 IRepository 实例。

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

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

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

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

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

public class EfRepository : IRepository
{
private readonly IDatabaseContext _context;

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

...methods for add, delete, 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, delete, update entities
}

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

...methods exposing EF for add, delete, 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();

关于asp.net-mvc - DbContext 已被释放并且 autofac,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14919543/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com