在启动时注册多个 DbContext 实例以在通用存储库中使用

Mic*_*ell 1 entity-framework-core .net-core asp.net-core

我正在尝试创建一个通用存储库,它接受 2 种通用类型,例如

public class EfRepository<T, TS> : IAsyncRepository<T,TS> where T : BaseEntity
                                                           where TS : DbContext
    {
..........
}
Run Code Online (Sandbox Code Playgroud)

在我的 startup.cs 我有通常的映射:

services.AddScoped<DbContext, ConfigDbContext>();

我现在如何向 DbContext 添加另一个映射?我尝试在 DbContext 和我创建的另一个上下文之间添加另一个映射,但它只使用第一个映射。

我有多个需要使用的数据库,理想情况下希望每个数据库都有一个 DbContext,但我看不到具有多个 DI 映射的方法。

在我的 EfRepository 类中,当我向代码中添加额外的 DbContext 并使用它时,以下代码异常:

protected readonly DbContext _dbContext;
        public EfRepository(DbContext dbContext)
        {
            this._dbContext = (TS)dbContext;
        }
Run Code Online (Sandbox Code Playgroud)

例外是无法从 Type1 转换为 Type2,我知道这是因为 DbContext 绑定到我的 startup.cs 中的 Type1。

我如何(如果可能)以通用方式使用多个 DbContext?

Chr*_*att 5

这不是您注册的方式DbContext,这是您问题的根源。正确的方法是:

services.AddDbContext<ConfigDbContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("Foo")));
Run Code Online (Sandbox Code Playgroud)

正确完成,添加另一个完全相同:

services.AddDbContext<SomeOtherContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("OtherConnectionString")));
Run Code Online (Sandbox Code Playgroud)

然后,哪个被拉取取决于您注入的哪个,是的,确实意味着您需要指定要注入的实际类型,而不是DbContext一般。但是,只能在派生类中做到这一点。换句话说,您可以保留您拥有的代码(尽管您不应该强制转换上下文)并且只需执行以下操作:

public class FooRepository : EFRepository<Foo, ConfigDbContext>
{
    public FooRepository(ConfigDbContext context)
        : base(context) {}
}
Run Code Online (Sandbox Code Playgroud)

您可以将其保留为DbContext,因为您不需要实际类型来执行 EF 操作。要获得DbSets,您可以使用泛型Set<T>

var foos = _dbContext.Set<Foo>();
Run Code Online (Sandbox Code Playgroud)

现在,说了这么多,把它全部扔掉。将存储库模式与像 EF 这样的 ORM 一起使用是完全不可接受的。EF已经实现了存储库和工作单元模式。这DbContext是您的工作单元,每个单元DbSet都是一个存储库。在此之上添加一个额外的层只会为您的代码添加维护问题和额外的熵,坦率地说,创建一个与 EF 配合得很好的存储库/工作单元是如此努力以至于不可能,所以通常情况下,你只会削弱 EF,使其效率降低且更难使用。

使用像 EF 这样的 ORM 就是选择使用第三方 DAL。就这些。此时无需创建自己的 DAL,因为您已经将其外包。我不知道为什么这么多人挂在这个上面。您最后一次创建自己的路由框架或自己的模板化视图预处理器是什么时候。绝不。您只是为此(框架)使用第三方库,那么为什么将第三方库也用于您的 DAL 会出现问题?

然后,您会很好地询问如何抽象 EF 依赖项。好吧,首先,如果您认为有一天您可能会切换 ORM,那么您不会。它只是永远不会发生。您很快就会从头开始重写整个应用程序。其次,存储库模式甚至没有实现这一点。您仍然有一个 EF 依赖项,它一直冒泡到前线应用程序。没有办法解决这个问题。

对于真正的抽象,您可以使用微服务架构之类的东西。除此之外,只需拥抱依赖或根本不使用它,并真正创建自己的 DAL。