为了账号安全,请及时绑定邮箱和手机立即绑定

多线程 API 应用程序中的 EF 核心 DbContext

多线程 API 应用程序中的 EF 核心 DbContext

C#
至尊宝的传说 2022-12-24 10:09:22
tl;dr如何在多线程 .NET Core API 应用程序中使用 Entity Framework,即使 DbContext 不是线程安全的?语境我正在开发一个 .NET Core API 应用程序,它公开了几个访问数据库并从中读取数据的 RESTful 接口,同时运行多个 TimedHostedServices 作为后台工作线程,定期从其他 Web 服务轮询数据并将它们存储到数据库中。我知道 DbContext 不是线程安全的。我在 Stackoverflow 上阅读了很多文档、博客文章和答案,我可以找到很多(部分矛盾的)答案,但在使用 DI 时没有真正的“最佳实践”。我试过的东西ServiceLifetime.Scoped通过扩展方法使用默认值AddDbContext会由于竞争条件而导致异常。我不想使用锁(例如信号量),因为明显的缺点是:代码被锁污染,try/catch/finally 安全释放锁它看起来并不“稳健”,即当我忘记锁定访问 DbContext 的区域时。在处理同时处理并发连接和访问的数据库时,在应用程序中人为同步数据库访问似乎是多余的和“不自然的”不是注入MyDbContext而是DbContextOptions<MyDbContext>仅在我需要访问数据库时构建上下文,using在读/写之后使用语句立即处理它似乎有很多资源使用开销和不必要的许多连接打开/关闭。题我真的很困惑:这怎么能实现?我不认为我的用例是超级特殊的——从后台工作人员填充数据库并从 Web API 层查询它——所以应该有一种有意义的方法来使用 ef 核心来完成这项工作。非常感谢!
查看完整描述

2 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

您应该在TimedHostedServices触发时创建一个范围。


在构造函数中注入服务提供者:


public MyServiceService(IServiceProvider services)

{

    _services = services;

}

然后在任务触发时创建一个范围


using (var scope = _services.CreateScope())

{

    var anotherService = scope.ServiceProvider.GetRequiredService<AnotherService>();


    anotherService.Something();

}

文档中提供了更完整的示例



查看完整回答
反对 回复 2022-12-24
?
冉冉说

TA贡献1877条经验 获得超1个赞

另一种创建自己的 DbContextFactory 并为每个查询实例化新实例的方法。


public class DbContextFactory

{

    public YourDbContext Create()

    {

        var options = new DbContextOptionsBuilder<YourDbContext>()

            .UseSqlServer(_connectionString)

            .Options;


        return new YourDbContext(options);

    }

}

用法


public class Service

{

    private readonly DbContextFactory _dbContextFactory;


    public Service(DbContextFactory dbContextFactory) 

         => _dbContextFactory = dbContextFactory;


    public void Execute()

    {

        using (var context = _dbContextFactory.Create())

        {

            // use context

        }

    }

}    

使用工厂,您无需再担心范围,并使您的代码摆脱 ASP.NET Core 依赖项。

您将能够异步执行查询,这对于没有变通办法的范围 DbContext 是不可能的。

您始终对调用时保存的数据充满信心.SaveChanges(),其中使用作用域 DbContext 可能会在其他类中更改某些实体。


查看完整回答
反对 回复 2022-12-24
  • 2 回答
  • 0 关注
  • 115 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信