使用通用存储库模式时,DatabaseContext 总是会重新初始化并且不会保持状态
DatabaseContext always got reinitialized and didn't keep states when using generic repository pattern
试图找出如何在我的应用程序上共享我的上下文的相同实例,但 DBContext 在每个失去其状态的请求中不断重新初始化。
我有一个 dbfactory 负责初始化我的上下文。
public class DbFactory: Disposable, IDbFactory
{
GamaTaskDbContext dbContext;
public GamaTaskDbContext Init()
{
return dbContext ?? (dbContext = new GamaTaskDbContext());
}
protected override void DisposeCore()
{
if (dbContext != null)
dbContext.Dispose();
}
}
我还有一个通用存储库 class,其中的问题是每个请求都会触发存储库构造函数并发现 dbContext 为空并重新初始化它,因此对于每个请求我都有新的上下文实例 class 这导致我当然无法删除实体,因为获取数据的上下文与试图删除它的上下文不同。
public abstract class Repository<Tentity> where Tentity : class
{
private GamaTaskDbContext dataContext;
private readonly IDbSet<Tentity> dbSet;
protected IDbFactory DbFactory
{
get;
private set;
}
protected GamaTaskDbContext DbContext
{
get { return dataContext ?? (dataContext = DbFactory.Init());}
}
public Repository(IDbFactory dbFactory)
{
DbFactory = dbFactory;
dbSet = DbContext.Set<Tentity>();
}
IOC 配置
private static void SetAutofacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
// Repositories
builder.RegisterAssemblyTypes(typeof(CustomerRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces().InstancePerRequest();
// Services
builder.RegisterAssemblyTypes(typeof(CustomerService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => new MapperConfiguration(cfg => {
foreach (var profile in c.Resolve<IEnumerable<Profile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
builder.Register(c => c.Resolve<MapperConfiguration>()
.CreateMapper(c.Resolve))
.As<IMapper>()
.InstancePerLifetimeScope();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
依赖注入只是调用者控制所有依赖项的模式。这不仅意味着调用者是决定每个接口使用哪个 class 的人,而且还决定注入对象的寿命。
反转控制容器不仅用于解决所有依赖关系,还用于确保在需要时创建新对象,并在适当的时候处理所有一次性对象。
必须具有特定生命周期的对象称为作用域对象。对于 Web 应用程序,生命周期范围通常是 HTTP 请求的持续时间。
在您的示例中,您试图既保持控制又让控制反转容器完成工作。让容器管理您的 dbcontext 的生命周期。通过这样做,它将在第一个 class 请求它作为依赖项时创建它,然后将相同的 dbContext 实例传递给所有其他需要它的 classes。
放下控制,万事大吉
因此我只需要这段代码:
public abstract class Repository<Tentity> where Tentity : class
{
private GamaTaskDbContext _dataContext;
private readonly IDbSet<Tentity> dbSet;
public Repository(GamaTaskDbContext dataContext)
{
_dataContext = dataContext;
dbSet = _dataContext .Set<Tentity>();
}
protected GamaTaskDbContext DbContext
{
get { return _dataContext; }
}
然后这样注册:
builder.RegisterType<GamaTaskDbContext>().InstancePerLifetimeScope();
无需执行任何其他操作。
很少有您真正希望 DbContext 在多个 http 请求期间存在的情况。通常它只是伤害大于你的收获。
试图找出如何在我的应用程序上共享我的上下文的相同实例,但 DBContext 在每个失去其状态的请求中不断重新初始化。 我有一个 dbfactory 负责初始化我的上下文。
public class DbFactory: Disposable, IDbFactory
{
GamaTaskDbContext dbContext;
public GamaTaskDbContext Init()
{
return dbContext ?? (dbContext = new GamaTaskDbContext());
}
protected override void DisposeCore()
{
if (dbContext != null)
dbContext.Dispose();
}
}
我还有一个通用存储库 class,其中的问题是每个请求都会触发存储库构造函数并发现 dbContext 为空并重新初始化它,因此对于每个请求我都有新的上下文实例 class 这导致我当然无法删除实体,因为获取数据的上下文与试图删除它的上下文不同。
public abstract class Repository<Tentity> where Tentity : class
{
private GamaTaskDbContext dataContext;
private readonly IDbSet<Tentity> dbSet;
protected IDbFactory DbFactory
{
get;
private set;
}
protected GamaTaskDbContext DbContext
{
get { return dataContext ?? (dataContext = DbFactory.Init());}
}
public Repository(IDbFactory dbFactory)
{
DbFactory = dbFactory;
dbSet = DbContext.Set<Tentity>();
}
IOC 配置
private static void SetAutofacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
// Repositories
builder.RegisterAssemblyTypes(typeof(CustomerRepository).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces().InstancePerRequest();
// Services
builder.RegisterAssemblyTypes(typeof(CustomerService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => new MapperConfiguration(cfg => {
foreach (var profile in c.Resolve<IEnumerable<Profile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
builder.Register(c => c.Resolve<MapperConfiguration>()
.CreateMapper(c.Resolve))
.As<IMapper>()
.InstancePerLifetimeScope();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
依赖注入只是调用者控制所有依赖项的模式。这不仅意味着调用者是决定每个接口使用哪个 class 的人,而且还决定注入对象的寿命。
反转控制容器不仅用于解决所有依赖关系,还用于确保在需要时创建新对象,并在适当的时候处理所有一次性对象。
必须具有特定生命周期的对象称为作用域对象。对于 Web 应用程序,生命周期范围通常是 HTTP 请求的持续时间。
在您的示例中,您试图既保持控制又让控制反转容器完成工作。让容器管理您的 dbcontext 的生命周期。通过这样做,它将在第一个 class 请求它作为依赖项时创建它,然后将相同的 dbContext 实例传递给所有其他需要它的 classes。
放下控制,万事大吉
因此我只需要这段代码:
public abstract class Repository<Tentity> where Tentity : class
{
private GamaTaskDbContext _dataContext;
private readonly IDbSet<Tentity> dbSet;
public Repository(GamaTaskDbContext dataContext)
{
_dataContext = dataContext;
dbSet = _dataContext .Set<Tentity>();
}
protected GamaTaskDbContext DbContext
{
get { return _dataContext; }
}
然后这样注册:
builder.RegisterType<GamaTaskDbContext>().InstancePerLifetimeScope();
无需执行任何其他操作。
很少有您真正希望 DbContext 在多个 http 请求期间存在的情况。通常它只是伤害大于你的收获。