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

查看:33
本文介绍了我可以从现有的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< DbContext> (或创建自己的工厂):

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);
        });

在您的类中插入 Func< DisposableScopedContextWrapper>func 并使用它

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

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

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

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