启动时注册多个DbContext实例以在通用存储库中使用 [英] Registering multiple DbContext Instances on startup for use in Generic Repository

查看:44
本文介绍了启动时注册多个DbContext实例以在通用存储库中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a Generic repository which accepts 2 generic types e.g.

public class EfRepository<T, TS> : IAsyncRepository<T,TS> where T : BaseEntity
                                                           where TS : DbContext
    {
..........
}

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

and in my startup.cs I have the usual mapping:

services.AddScoped< DbContext,ConfigDbContext>();

我现在如何向DbContext添加另一个映射?我尝试在DbContext和我创建的另一个Context之间添加另一个映射,但是它仅使用第一个映射.

How can I now add another mapping to DbContext? I have tried adding another mapping between DbContext and another Context i created but It only ever uses the first mapping.

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

I have multiple databases I need to consume and would ideally like to have a DbContext for each one but i can't see a way of having multiple DI mappings.

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

In my EfRepository class the following code exceptions when I add an extra DbContext to my code and use it:

protected readonly DbContext _dbContext;
        public EfRepository(DbContext dbContext)
        {
            this._dbContext = (TS)dbContext;
        }

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

The exception is Unable to Convert from Type1 to Type2 and I know this is because the DbContext is bound to Type1 in my startup.cs.

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

How can I (if possible) use multiple DbContext's in a generic fashion?

推荐答案

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

That's not how you register DbContext, which is the source of your problem. The correct method is:

services.AddDbContext<ConfigDbContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("Foo")));

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

Done correctly, adding another is exactly the same:

services.AddDbContext<SomeOtherContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("OtherConnectionString")));

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

Then, which one gets pulled depends on which one you inject, which yes, does mean that you need to specify the actual type you want to inject, not DbContext generically. However, that can be done only one the derived class. In other words, you can keep the code you have (though you should not cast the context) and simply do:

public class FooRepository : EFRepository<Foo, ConfigDbContext>
{
    public FooRepository(ConfigDbContext context)
        : base(context) {}
}

您可以将其保留为 DbContext ,因为您不需要实际的类型即可执行EF操作.要获取 DbSet ,可以使用通用的 Set< T> :

You can leave it upcast to DbContext, as you don't need the actual type to do EF things. To get at the DbSets, you can use the generic Set<T>:

var foos = _dbContext.Set<Foo>();

现在,话虽这么说,把它全部扔掉.将存储库模式与EF之类的ORM一起使用是完全不可接受的.EF 已经已实现存储库和工作单元模式. DbContext 是您的工作单元,每个 DbSet 是一个存储库.在此之上添加额外的层无济于事,但会增加代码的维护问题和额外的熵,并且坦率地说,创建与EF配合良好的存储库/工作单元的尝试是不可能的,因此通常是不可行的.,您将束缚EF,从而使EF效率降低且难于使用.

And now, with all that said, throw it all out. It's completely unacceptable to use the repository pattern with an ORM like EF. EF already implements the repository and unit of work patterns. The DbContext is your unit of work, and each DbSet is a repository. Adding an extra layer on top of that does nothing but add maintenance concerns and extra entropy to your code, and frankly, creating a repository/unit of work that plays nice with EF, is so trying as to be impossible, so more often than not, you're just going to hamstring EF, making it less efficient and harder to use.

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

Using an ORM like EF is choosing to use a third-party DAL. That is all. There's no need to create your own DAL at that point, because you've outsourced it. I'm not sure why so many people get hung up on this. When was the last time you created your own routing framework or your own templated view preprocessor. Never. You just third party libraries for that (the framework), so why is it a problem to use a third party library for your DAL as well?

然后,您要问清楚抽象EF依赖项的方法.好吧,首先,如果您想在某天转换ORM,则不会.只是永远不会发生.您将更快地从头开始重写整个应用程序.其次,存储库模式甚至无法实现这一目标.您仍然有一个EF依赖关系,一直到前线应用程序冒泡.没办法解决.

Then, you make ask well what about abstracting the EF dependency. Well, first, if you're thinking you might switch ORMs some day down the road, you won't. It just never happens. You'll sooner rewrite the whole app from the ground up. Second, the repository pattern doesn't even achieve this. You still have an EF dependency that bubbles all the way up to the front-line app. There's no way around that.

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

For true abstraction, you can use something like microservices architecture. Other than that, just embrace the dependency or don't use it at all, and really create your own DAL.

这篇关于启动时注册多个DbContext实例以在通用存储库中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆