【发布时间】:2016-08-05 04:40:37
【问题描述】:
我有一个带有 EF7 的 Asp.net 5/Core 1 应用程序。我在DI容器中正常注册了DbContext。
services.AddEntityFramework().AddSqlServer()
.AddDbContext<MyDbContext>(options => options.UseSqlServer(connection));
这是一个小样本,展示了我正在尝试做的事情。
public class MyController : Controller
{
MyDbContext _myDbContext;
public MyController(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public IActionResult Index()
{
//Just start these and don't wait for them to finish
//We don't care if they succeed or not
Task.Run(() => DoSomeLogging1());
Task.Run(() => DoSomeLogging2());
return View();
}
private void DoSomeLogging1()
{
_myDbContext.Items.ToList();
}
private void DoSomeLogging2()
{
_myDbContext.Items.ToList();
}
}
这两个 DoSomeLoggingX 方法都将使用注入到控制器的 MyDbContext 实例。由于这些方法在同时执行数据库查询的同时运行,因此另一个方法总是会失败
连接没有关闭。连接的当前状态是 连接。
MyDbContext 也使用 DI 来获取一些引用,所以即使我想要也不能直接使用它。
如何在并行运行代码的同时仍然能够通过实体框架使用我的数据库?
【问题讨论】:
-
你能展示你整个动作的代码吗?您似乎没有等待任务完成。
-
首先,不要在 ASP.NET 中生成后台线程,这是一个非常糟糕的做法。对于 ASP.NET 应用程序,线程是您拥有的最重要的资源。如果您执行异步操作,您应该使用 await/async,这会释放线程,直到异步操作完成。如果您在 请求线程 上执行 CPU 敏感操作,请不要为它启动一个新操作。 ASP.NET 中的 DbContexts 默认注册为作用域,这意味着它们将在请求期间解析并存在。当请求结束时,它们将被释放。
-
如果你真的想做一些日志记录并立即返回,你需要使用某种消息总线,你触发日志事件,它们在消息总线中排队并由一些服务处理具有更长生命周期(即应用程序生命周期)的 dbcontext 并在那里进行日志处理,或者如果您使用分布式架构(rabbitmq 或其他 AMQP 系统)并有一个单独的进程从队列中获取消息并处理它们
-
所以请澄清你对为什么需要这种东西的意图。我很确定您的意图是/是“释放”请求,因此您不会“阻止”其他用户的请求,但您所达到的恰恰相反:现在您在异步操作期间使用 2 个线程而不是 0
-
上面的视图是一个搜索表单(示例中省略了提交的动作)。搜索搜索一些已填充的内存数据。上述 DoSomeLogging 方法应命名为 UpdateInMemoryDataIfNeeded。因此,他们检查持久化数据是否足够新鲜,如果没有,则从外部源获取新数据,并在完成后将内存中的数据替换为新数据。
标签: c# dependency-injection asp.net-core entity-framework-core