我可以从现有的 DbContext 克隆吗? [英] Can I clone DbContext from existing one?

查看:24
本文介绍了我可以从现有的 DbContext 克隆吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究 .NET Core Web API,我有一个端点,我想在其中并行运行三个操作.他们三个都使用同一个数据库,所以我需要三个 DbContext 副本.我创建了一个简单的 Factory 类,稍后将其注入到我的Data"类中.

I'm working on .NET Core Web API and I have one endpoint where I want to run three operations in parallel. All three of them use the same database, so I need three copies of DbContext. I created a simple Factory class, which I later inject into my "Data" class.

是否有可能(如果是,这是一个很好的做法),将 DbContext 注入我的工厂类(使用内置的 .NET Core IoC),并且当有人调用CreateMyDbContext"方法时,只需深度克隆在开始?

Is it possible (if it's, is a good practice), to inject DbContext into my factory class (using built in .NET Core IoC) and when someone calls "CreateMyDbContext" method, just deep clone the one which was injected at the beginning?

以下是 DbContext 池的示例:

Here is the example with the DbContext Pool:

public class FooData : IFooData
{
    private readonly Func<DisposableScopedContextWrapper> _func;

    public FooData(Func<DisposableScopedContextWrapper> func)
    {
        _func = func;
    }

    public async Task<List<Apple>> GetApples()
    {
        using (var wrapper = _func())
        {
            var apples = await wrapper.Context.Apples.FromSqlRaw("SELECT.... complicated query").ToListAsync();
            return apples;
        }
    }

    public async Task<List<Orange>> GetOranges()
    {
        using (var wrapper = _func())
        {
            var oranges = await wrapper.Context.Oranges.FromSqlRaw("SELECT.... complicated query").ToListAsync();
            return oranges;
        }
    }
}


public class FooService
{
    private readonly IFooData _fooData;

    public FooData(IFooData fooData)
    {
        _fooData = fooData;
    }

    public async Task<List<Fruit>> GetFruits()
    {
        var appleTask = _fooData.GetApples();
        var orangeTask = _fooData.GetOranges();

        (var result1, var result2) = await (appleTask, orangeTask).WhenAll();

        // ... 
    }
}

推荐答案

出于多种原因,我绝对不会推荐任何深度克隆,其中之一是您需要弄清楚很多 EF 内部结构才能使其正确,并且内部可以改变(你需要花一些时间在上面).

I definitely would not recommend any deepcloning for multiple reasons, one of them being that you will need to figure out a lot of EF internals to make it right, and internals can change(and you will need to spend some time on it).

第二个选项是手动创建上下文,我建议不要这样做,因为现代基础设施使用 DbContext 池化.

Second option would be just creating your context manually, which I would recommend against also cause modern infrastructure uses DbContext pooling.

那么您可以像这样注册 Func(或创建您自己的工厂):

So what you can to register Func<DbContext> (or create your own factory) like this:

 services.AddSingleton<Func<DbContext>>(provider => () => 
        {
            var scope = provider.CreateScope();
            return scope.ServiceProvider.GetRequiredService<DbContext>();
        });    

这里的问题是这里的范围不会被释放,你不能(如果你的 DbContext 有默认范围)在 Func 原因内释放范围您的上下文也将被处理.因此,您可以尝试创建一些一次性包装器,以便您可以像这样手动处理所有内容:

the issue here is that scope here would not be disposed and you can't(if you have default scope for your DbContext) dispose the scope inside the Func cause your context will be disposed also. So you can try creating some disposable wrapper so you can manually dispose everything like this:

    public class DisposableScopedContextWrapper : IDisposable
    {
        private readonly IServiceScope _scope;
        public DbContext Context { get; }

        public DisposableScopedContextWrapper(IServiceScope scope)
        {
            _scope = scope;
            Context = _scope.ServiceProvider.GetService<DbContext>();
        }

        public void Dispose()
        {
            _scope.Dispose();
        }
    } 

    services.AddSingleton<Func<DisposableScopedContextWrapper>>(provider =>() => 
        {
            var scope = provider.CreateScope();
            return new DisposableScopedContextWrapper(scope);
        });

在你的类中注入 Funcfunc 并使用它

Inject in your classes Func<DisposableScopedContextWrapper> func and use it

 using (var wrapper = func())
        {
            wrapper.Context...
        }

这篇关于我可以从现有的 DbContext 克隆吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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