可以使用多个DbContext的服务吗?

huangapple go评论77阅读模式
英文:

Service with several DbContext possible?

问题

在一个测试项目中,我有以下层次结构:
Web API <-> Service(带有 DbContext)。

我不使用存储库模式,因为 DbSet 已经是一个存储库。

public class MyService : DbContext
{
    public MyService(DbContextOptions<MyDbContext> options)
        : base(options)
    {
    }
    ...
}

我在思考是否应该为每个服务注入 DbContext,还是在每个方法内部使用 using 语句创建 DbContext

DoSomething()
{
   using (var db = new DbContext())
   {
      ...
   }
}

后者的优点是我可以并行运行不同的查询(我有这种情况,目前三个查询按顺序运行)。或者我可以将两种情况结合起来吗?

英文:

In a test project I have the following layers:
Web API <-> Service (with DbContext).

I do not use the repository pattern because DbSet is already a repository.

public class MyService : DbContext
{
    public MyService(DbContextOptions&lt;MyDbContext&gt; options)
        : base(options)
    {
    }
    ...
}

I'm wondering if I should inject the DbContext for each service, or create the DbContext within a using statement per method?

DoSomething()
{
   using (var db = new DbContext())
   {
      ...
   }
}

The advantage of the latter would be that I can run different queries in parallel (I have the case, and at the moment three queries are running sequentially).

Or can I even combine both cases?

答案1

得分: 3

我会主张第二种方法在一定程度上违反了依赖注入(DI)原则。是的,你可以在DI中设置并注入 DbContextOptions&lt;MyDbContext&gt;,然后在上下文构建中使用它们,但可以说更好的方法是使用 IDbContextFactory 方法:

services.AddDbContextFactory&lt;ApplicationDbContext&gt;(opts =&gt; ...);

然后在服务中注入并使用它:

private readonly IDbContextFactory&lt;ApplicationDbContext&gt; _contextFactory;

public MyService(IDbContextFactory&lt;ApplicationDbContext&gt; contextFactory)
{
    _contextFactory = contextFactory;
}

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext()) // 应该在使用完上下文后进行释放以确保正确使用
    {
        // ...
    }
}

请注意,以这种方式创建的 DbContext 实例不由应用程序的服务提供程序管理,因此必须由应用程序进行处理。

或者我是否可以将这两种情况结合起来使用?

上下文工厂方法允许同时解析工厂和上下文。

请注意,在Web应用程序方面,关于是否实际上有必要并行查询数据库存在一些争议(至少不作为默认方法)。

英文:

I would argue that second approach goes a bit against the DI principle. Yes, you can setup in DI and inject the DbContextOptions&lt;MyDbContext&gt; and use them for context construction but arguably better approach would be using IDbContextFactory approach:

services.AddDbContextFactory&lt;ApplicationDbContext&gt;(opts =&gt; ...);

And then inject and use it in the service:

private readonly IDbContextFactory&lt;ApplicationDbContext&gt; _contextFactory;

public MyService(IDbContextFactory&lt;ApplicationDbContext&gt; contextFactory)
{
    _contextFactory = contextFactory;
}

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext()) // should dispose the context for correct usage
    {
        // ...
    }
}

> > Notice that the DbContext instances created in this way are not managed by the application's service provider and therefore must be disposed by the application.

> Or can I even combine both cases?

The context factory approach allows to resolve both factory and context.

Note that in terms of Web applications there is some debate if it actually useful to query the database in parallel (at least as default approach).

答案2

得分: -1

以下是在C#中创建具有多个DbContext的服务的步骤:

创建一个名为DbContextFactory的类。

  1. 此类将负责创建和返回不同DbContext的实例。
  2. 在DbContextFactory类中,创建一个DbContext的字典。字典的键将是DbContext的名称,值将是DbContext的实例。
  3. 在DbContextFactory类中,创建一个名为GetDbContext的方法。此方法将以DbContext的名称作为参数,并返回DbContext的实例。
  4. 在Startup类中,将DbContextFactory类注册为服务。
    在您的代码中,需要访问DbContext的地方,请使用DbContextFactory类获取DbContext的实例。

以下是DbContextFactory类的示例:

public class DbContextFactory
{
    private static Dictionary<string, DbContext> _dbContexts = new Dictionary<string, DbContext>();

    public DbContext GetDbContext(string name)
    {
        if (!_dbContexts.ContainsKey(name))
        {
            _dbContexts[name] = new DbContext(name);
        }

        return _dbContexts[name];
    }
}

以下是如何使用DbContextFactory类的示例:

var dbContext = DbContextFactory.GetDbContext("MyDbContext");
英文:

Here are the steps on how to create a service with several DbContext in C#:

Create a class called DbContextFactory.

  1. This class will be responsible for creating and returning instances of the different DbContexts.
  2. In the DbContextFactory class, create a dictionary of DbContexts. The key of the dictionary will be the name of the DbContext, and the value will be the instance of the DbContext.
  3. In the DbContextFactory class, create a method called GetDbContext. This method will take the name of the DbContext as a parameter and return the instance of the DbContext.
  4. In the Startup class, register the DbContextFactory class as a service.
    In your code, where you need to access a DbContext, use the DbContextFactory class to get the instance of the DbContext.

Here is an example of the DbContextFactory class:

public class DbContextFactory
{
    private static Dictionary&lt;string, DbContext&gt; _dbContexts = new Dictionary&lt;string, DbContext&gt;();

    public DbContext GetDbContext(string name)
    {
        if (!_dbContexts.ContainsKey(name))
        {
            _dbContexts[name] = new DbContext(name);
        }

        return _dbContexts[name];
    }
}

Here is an example of how to use the DbContextFactory class:

var dbContext = DbContextFactory.GetDbContext(&quot;MyDbContext&quot;);

huangapple
  • 本文由 发表于 2023年7月3日 17:20:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76603428.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定