我一直在阅读很多文章,解释如何设置实体框架,DbContext以便每个HTTP Web请求只使用各种DI框架创建和使用一个.
为什么这首先是一个好主意?使用这种方法有什么好处?在某些情况下这是个好主意吗?在使用DbContext存储库方法调用实例化s 时,您是否可以使用此技术执行某些操作?
我可能没想到正确的方向.我对Dependency Injection和ASP.Net Core相当新.
我有一个ASP.Net核心网站,其中一个任务是将数据从Excel工作表导入用户将上传的数据库.excel表格可能很大,数据转换任务也很耗时,因此我希望在后台执行它们.即用户将上传工作表,响应将立即发送,后台作业/线程将导入数据.
我正在尝试通过以下方式运行后台作业:
Task.Run(() => ProcessImport(model));
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是Process导入方法调用具有存储库类的服务,这些存储库类通过作为Scoped添加的ASP.Net依赖注入容器访问AppDbContext,并且一旦响应被发回,就会释放上下文.我收到一个运行时异常,你不能在它被处置后使用上下文.
我的问题是,处理这种情况的最佳方法是什么?我应该制作AppDbContext单例吗?我应该在ProcessImport方法中创建一个新的AppDbContext实例,并将其传递给它吗?我看过DbContext不是线程安全的,所以这是一个好方法吗?
dependency-injection background-process entity-framework-core asp.net-core-mvc asp.net-core
我们有一个应用程序使用我们的供应商提供的 SDK 来轻松地与他们集成。此 SDK 连接到 AMQP 端点,并简单地向我们的消费者分发、缓存和转换消息。以前,这种集成是通过 HTTP 使用 XML 作为数据源的,而旧的集成有两种缓存 DataContext 的方法 - 每个 Web 请求和每个托管线程 ID。(1)
但是,现在我们不通过 HTTP 集成,而是通过 AMQP 集成,这对我们来说是透明的,因为 SDK 正在执行所有连接逻辑,我们只剩下定义我们的使用者,因此没有选项可以“根据 Web 请求”缓存 DataContext,因此只剩下每个托管线程 id。我实现了责任链模式,所以当我们收到更新时,它被放在一个处理程序管道中,该管道使用 DataContext 根据新的更新更新数据库。这是管道的调用方法的样子:
public Task Invoke(TInput entity)
{
object currentInputArgument = entity;
for (var i = 0; i < _pipeline.Count; ++i)
{
var action = _pipeline[i];
if (action.Method.ReturnType.IsSubclassOf(typeof(Task)))
{
if (action.Method.ReturnType.IsConstructedGenericType)
{
dynamic tmp = action.DynamicInvoke(currentInputArgument);
currentInputArgument = tmp.GetAwaiter().GetResult();
}
else
{
(action.DynamicInvoke(currentInputArgument) as Task).GetAwaiter().GetResult();
}
}
else
{
currentInputArgument = action.DynamicInvoke(currentInputArgument); …Run Code Online (Sandbox Code Playgroud) 我阅读了很多有关 Efcore 中的 DBcontext 及其生命周期的文档和文章,但是,我有一些问题。
基于此链接“ https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration /” DBcontext 的最佳生命周期和 AddDbContext 的默认生命周期是scope,但是下面两者存在矛盾本文档中的句子。
“ DbContext 不是线程安全的。不要在线程之间共享上下文。请确保在继续使用上下文实例之前等待所有异步调用。”
另一方面,也有人提到,
“在大多数 ASP.NET Core 应用程序中,Dbcontext 不会出现并发访问问题,因为在给定时间只有一个线程执行每个客户端请求,并且每个请求都有一个单独的依赖项注入范围(因此有一个单独的 DbContext 实例)。”
此外,我阅读了一些禁止注册单例 DbContext 的文档,但是AddDbContextPool 允许注册单例 DBcontext。所以有一些关于Dbcontextpool的问题。
multithreading dependency-injection dbcontext entity-framework-core .net-core
所以我目前正在使用一个使用Entity Framework的ASP.NET MVC Web应用程序,我也使用Ninject进行依赖注入.
所以基本上,目前,这是我用Ninject注册我的DbContext和服务的方式.
kernel.Bind<DbContext>().To<MyApplicationContext>().InSingletonScope();
kernel.Bind<IAccountService>().To<AccountService>().InSingletonScope();
kernel.Bind<IRegionService>().To<RegionService>().InSingletonScope();
kernel.Bind<IRoleService>().To<RoleService>().InSingletonScope();
Run Code Online (Sandbox Code Playgroud)
我注册它们InSingletonScope,这意味着它们只会被创建一次并在应用程序的整个生命周期中使用(至少我是如何理解的).
控制器:
private IAccountService _accountService;
public MemberController(IAccountService accountService)
{
_accountService = accountService;
}
Run Code Online (Sandbox Code Playgroud)
但是,我深深感到这个单例范围会导致我的Web应用程序出现问题,特别是对于Entity Framework的上下文,因为它是单例.
我已经面临一个小问题,如果我使用SQL Management Studio手动更新数据库,我的Web应用程序的实体框架中的数据将不会更新,直到我重新启动应用程序(似乎是EF中的一些缓存机制).
-
但是,如果我删除了InSingletonScope,我将随机从EF获取错误说:
IEntityChangeTracker的多个实例不能引用实体对象
我理解为什么会发生这种情况,因为初始化的DbContext AccountService可能与说不同RegionService.但我不知道如何解决这个问题.
我对依赖注入的理解仍然非常有限,所以有人可以建议吗?
-
编辑:我已经尝试改为InRequestScope所有注射,但我仍然得到
IEntityChangeTracker的多个实例不能引用实体对象
尝试从我的应用程序中的另一个服务插入具有相关对象(外键)的新实体时.这意味着他们仍在使用不同的DbContext,发生了什么?!
最后编辑:好的我发现了问题,这是我的缓存机制缓存了以前的请求,导致所有后续请求的关系问题.
c# asp.net-mvc entity-framework dependency-injection ninject
我的理解是不应该在并发Web请求之间共享DbContext实例,所以绝对不能跨线程.但是如何在非并发Web请求中共享它呢?
由于线程敏捷性(ASP.Net中线程敏捷性的含义是什么?),我是否正确,一个线程可以在它死之前处理多个Web请求?
如果是这样,依赖为每个线程注入DbContext实例是否安全?
原因是我使用Unity,它不包括每个请求的生命周期选项.从MVC,EF - DataContext单例实例Per-Web-Request在Unity中,我想我可以使用自定义LifetimeManager; 我只是想知道使用PerThreadLifetimeManager是否安全和充足.
asp.net-mvc entity-framework dependency-injection unity-container dbcontext
我想问下面的代码是否是线程安全的:考虑Save1和Save2将同时执行.datacontext的线程安全性有问题吗?
public class Test1()
{
private void Save1()
{
using(TestLinqToSQL obj = new TestLinqToSQL())
{
obj.SaveRecord(new Client (){Id = 1, Name = "John Doe");
}
}
private void Save2()
{
using(TestLinqToSQL obj = new TestLinqToSQL())
{
obj.SaveRecord(new Client (){Id = 2, Name = "Mike Tyson");
}
}
}
public class TestLinqToSQL : IDisposable
{
public void SaveRecord(Client newClient)
{
using(ClientDatacontext cont = new ClientDatacontext())
{
cont.InsertRecord(newClient);
}
}
}
Run Code Online (Sandbox Code Playgroud)
提前致谢
我正在使用.NET Core 3.1。我想运行一些后台处理,而用户不必等待它完成(大约需要 1 分钟)。因此,我Task.Run这样使用:
public class MyController : Controller
{
private readonly IMyService _myService;
public MyController(IMyService myService)
{
_myService = myService;
}
public async Task<IActionResult> Create(...)
{
await _myService.CreatePostAsync(...);
return View();
}
}
public class MyService : IMyService
{
private readonly MyDbContext _dbContext;
private readonly IServiceScopeFactory _scopeFactory;
public MyService(MyDbContext dbContext, IServiceScopeFactory scopeFactory)
{
_dbContext = dbContext;
_scopeFactory = scopeFactory;
}
public async Task CreatePostAsync(Post post)
{
...
string username = GetUsername();
DbContextOptions<MyDbContext> dbOptions = GetDbOptions(); …Run Code Online (Sandbox Code Playgroud) 我正在编写一个针对 dotnet core 框架 3.1 的应用程序。我使用依赖注入来配置数据库上下文等。在我的 Program.cs 中,我有以下代码:
var host = new HostBuilder()
.ConfigureHostConfiguration(cfgHost =>
{
...
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
....
})
.ConfigureServices((hostContext, services) =>
{
...
services.AddDbContext<MyHomeContext>(options =>
{
options.UseNpgsql(hostContext.Configuration.GetConnectionString("DbContext"));
}, ServiceLifetime.Transient);
...
})
.ConfigureLogging((hostContext, logging) =>
{
...
})
.Build();
Run Code Online (Sandbox Code Playgroud)
我转到host另一个班级。在另一个类中,作为较长方法的一部分,我有以下代码:
using (var context = Host.Services.GetService(typeof(MyHomeContext)) as MyHomeContext)
{
StatusValues = context.Status.ToDictionary(kvp => kvp.Name, kvp => kvp.Id);
}
GC.Collect();
GC.Collect();
Run Code Online (Sandbox Code Playgroud)
这些GC.Collect电话是出于测试/调查目的。在MyHomeContextI 中,出于测试目的,实现了析构函数和 Dispose() 的重写。Dispose() 被调用,但析构函数永远不会被调用。这会导致我创建的每个实例出现内存泄漏MyHomeContext。
我缺少什么?MyHomeContext我可以做什么来确保当我不再需要它时删除它的实例。 …
c# memory-leaks dependency-injection microsoft.extensions.hosting
我知道这DbContext不是线程安全的,加上DbContext缓存数据,当多个事务尝试将自己的更改保存/提交到数据库时,它可能会导致数据不一致。因此,强烈建议按请求注入它(这里)。但是我有一种情况,只有读取操作存在(在独立的类库中)并且没有事务或创建/更新/删除操作。
我的问题是:DbContext在这种情况下作为单例注入是否安全?
c# ×7
dbcontext ×3
asp.net-core ×2
asp.net-mvc ×2
datacontext ×2
.net ×1
.net-core ×1
asp.net ×1
ef-core-3.1 ×1
linq-to-sql ×1
memory-leaks ×1
microsoft.extensions.hosting ×1
ninject ×1