gpt4 book ai didi

entity-framework - 具有多个有界 DbContext 的简单注入(inject)器 - 异常 "IDbContext has already been registered"

转载 作者:行者123 更新时间:2023-12-04 18:43:21 26 4
gpt4 key购买 nike

我正在尝试切换到 简易喷油器 依赖注入(inject)框架,因为它的速度给我留下了深刻的印象。

 private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
////container.RegisterPerWebRequest<IDbContext, DbContext2>();
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();

其中 DbContext1 和 DbContext2 从 BaseDbContext 类继承
public class BaseDbContext<TContext> : DbContext, IDbContext where TContext : DbContext

它实现了一个相当简单的 IDbContext 接口(interface)(就像 SO 上提供的许多接口(interface)一样),例如:
public interface IDbContext
{
IQueryable<TEntity> Find<TEntity>() where TEntity : class;
DbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
void Dispose();
}

如果我只使用一个 DbContext 类,它可以正常工作 - 存储库被注入(inject)、数据被拉取等。

但是,我还想使用每个 DbSet 数量较少的有界上下文 ( Shrink EF Models with DDD Bounded Contexts),因为我的 Code-First DbContext 否则将包含数百个类
private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
container.RegisterPerWebRequest<IDbContext, DbContext2>();

container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();

然后我得到一个异常(exception):

System.InvalidOperationException was unhandled by user code HResult=-2146233079 Message=Type IDbContext has already been registered and the container is currently not configured to allow overriding registrations. To allow overriding the current registration, please set the Container.Options.AllowOverridingRegistrations to true. Source=SimpleInjector StackTrace: at SimpleInjector.Container.ThrowWhenTypeAlreadyRegistered(Type type) at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration) at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle, String serviceTypeParamName, String implementationTypeParamName) at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle) at SimpleInjector.SimpleInjectorWebExtensions.RegisterPerWebRequest[TService,TImplementation](Container container)



如果我遵循建议:
container.Options.AllowOverridingRegistrations = true;

然后 DbContext2 似乎覆盖了 DbContext1,例如DbSet "Colour"位于 DbContext1 中,不再可访问:
Additional information: The entity type Colour is not part of the model for the current context.

我应该如何一起使用 Simple Injector 和 bounded DbContexts?

[更新]

DbContexts 不直接在 Controller 中使用,它们是存储库的依赖项,Simple Injector 应该能够在构造函数中初始化
 public class ColoursController : ApiController
{
private readonly IColourRepository _repository;
private readonly ModelFactory _modelFactory;

public ColoursController(IColourRepository repository)
{
_repository = repository;
_modelFactory = new ModelFactory();
}

在哪里
 public class ColourRepository : Repository<Colour>, IColourRepository
{
public ColourRepository(IDbContext context) : base(context) { }

ColourRepository 需要 DbContext1 的具体实现,但其他一些存储库需要 DbContext2(具有不同的实体集)

我看不出为什么不能对 DbContext1 和 DbContext2 使用 IDbContext 接口(interface)(或基类型)的原因。

Unity 可以做到:
container.RegisterType<IDbContext, NorthwindContext>(new PerRequestLifetimeManager(), "NorthwindContext");
container.RegisterType<IDbContext, NorthwindCustomerContext>(new PerRequestLifetimeManager(), "NorthwindCustomerContext");

Ninject 可以做到。

Simple Injector 提到了 CompositeLogger - 也许那个可以解决问题?

https://simpleinjector.org/

最佳答案

ColourRepository expects a concrete implementation of DbContext1, but some other repository would need DbContext2 (with a different set of entities)



您的设计目前不明确。虽然你的设计谈到了 IDbContext看起来如果只有一个抽象具有两个实现,但这些实现不可互换( Liskov Substitution principle 违规),这表明实际上应该有两个不同的接口(interface)。此外,只有一个接口(interface)会使您的 DI 配置更加复杂且难以维护(这与您选择的框架无关)。

因此,解决方案是通过为每个上下文提供自己的界面来消除设计中的歧义。这允许您的存储库依赖于他们需要的抽象:

public class ColourRepository : Repository<Colour>, IColourRepository
{
public ColourRepository(ICustomerDbContext context) : base(context) { }
}

这使您可以简化注册:

container.Register<IDbContext, NorthwindContext>(Lifestyle.Scoped);
container.Register<ICustomerDbContext, NorthwindCustomerContext>(Lifestyle.Scoped);

请注意,使用键控注册不会解决核心问题;您仍将被迫明确声明应将哪个 key 版本注入(inject)哪个存储库,这将使您的 DI 配置成为维护噩梦并且非常容易出错。

关于entity-framework - 具有多个有界 DbContext 的简单注入(inject)器 - 异常 "IDbContext has already been registered",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19747521/

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