Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架核心-非线程安全-ServiceLifetime.Transient_C#_.net_Multithreading_Entity Framework_Entity Framework Core - Fatal编程技术网

C# 实体框架核心-非线程安全-ServiceLifetime.Transient

C# 实体框架核心-非线程安全-ServiceLifetime.Transient,c#,.net,multithreading,entity-framework,entity-framework-core,C#,.net,Multithreading,Entity Framework,Entity Framework Core,似乎我的数据库上下文不是线程安全的、暂时的,即使我指定了: ServiceLifetime.Transient 在数据库的启动配置中 Startup.cs 这将解决我的问题,因为默认值是有范围的,但没有 但是,如果我使用语句添加 public async Task<List<OrganisationEntity>> GetOrganisations(int? organisationId, List<int> statusIds) { var op

似乎我的数据库上下文不是线程安全的、暂时的,即使我指定了:

ServiceLifetime.Transient 
在数据库的启动配置中

Startup.cs

这将解决我的问题,因为默认值是有范围的,但没有

但是,如果我使用语句添加

public async Task<List<OrganisationEntity>> GetOrganisations(int? organisationId, List<int> statusIds)
{
    var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
    optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(
            "Data Source=.;Initial Catalog=MYDATABASE;Integrated Security=True;Connect Timeout=30;");

    using (var db = new DatabaseContext(optionsBuilder.Options, null))
    {
        IQueryable<OrganisationEntity> organisations =
            db.Organisation.Include(o => o.Status).OrderByDescending(d => d.Created).AsQueryable();

        if (organisationId != null)
        {
            organisations = organisations.Where(o => o.Id == organisationId);
        }

        if (statusIds != null && statusIds.Count > 0)
        {
            organisations = organisations.Where(o => statusIds.Contains(o.StatusId));
        }

        return await organisations.ToListAsync();
    }
}

public async Task<int> GetOrganisationCount()
{
    var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
    optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(
            "Data Source=.;Initial Catalog=MYDATABASE;Integrated Security=True;Connect Timeout=30;");

    using (var db = new DatabaseContext(optionsBuilder.Options, null))
    {
        return await db.Organisation.CountAsync();
    }
}
一切正常

为什么依赖注入不能正常工作

我完全错了吗?如果我需要临时上下文,我是否被迫在所有任务中使用using语句

服务寿命。暂时性窃听

编辑:

Stacktrade,一些信息被掩盖了

在 System.Data.ProviderBase.DBCONNECTIONCLOSEDCONNECTION.TryOpenConnectionDbConnection 外部连接,数据库连接工厂连接工厂, TaskCompletionSource1重试,DbConnectionOptions用户选项\r\n 位于System.Data.SqlClient.SqlConnection.TryOpenTaskCompletionSource1 重试\r\n在 System.Data.SqlClient.SqlConnection.OpenAsyncCancellationToken cancellationToken\r\n--来自上一个位置的堆栈结束跟踪 在引发异常的位置--\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.d\u 31.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable.AsyncEnumerator.d\u 9.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Storage.Internal.SqlServerExecutionStrategy.d\u 62.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable.AsyncEnumerator.d\u 8.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Query.AsyncQueryMethodProvider.d\u 161.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Query.Internal.TaskResultAsyncEnumerable1.Enumerator.d\u 3.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor 1.EnumeratorExceptionInterceptor.d\u 5.MoveNext\r\n-- 来自引发异常的上一个位置的堆栈结束跟踪 --\r\n位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 System.Runtime.CompilerServices.TaskWaiter1.GetResult\r\n位于 XXXXXXX.Data.Repositories.organization.organizationRepository.d_u8.MoveNext 在C:\\Users\\XXXXXXX\\Documents\\visualstudio中 2017\\Projects\\XXXXXXX\\XXXXXXX.Data\\Repositories\\organization\\organizationrepository.cs:line 65\r\n--来自上一个异常所在位置的堆栈结束跟踪 被抛出--\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 System.Runtime.CompilerServices.TaskWaiter1.GetResult\r\n位于 XXXXXXX.Api.Services.organization.organizationservice.d__4.MoveNext 在C:\Users\XXXXXXX\Documents\Visual Studio中 2017\Projects\XXXXXXX\XXXXXXX.Api\Services\organization\organizationservice.cs:line 31\r\n--来自上一个异常所在位置的堆栈结束跟踪 被抛出--\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw\r\n 在 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotificationTask 任务\r\n位于 System.Runtime.CompilerS services.TaskAwaiter.GetResult\r\n位于 XXXXXXX.Api.Controllers.Administration.organizationcontrollers.d__5.MoveNext 在C:\Users\XXXXXXX\Documents\Visual Studio中 2017\Projects\XXXXXXX\XXXXXXX.Api\Controllers\Administration\organizationcontroller.cs:line 五十一

服务寿命。暂时性窃听

这不是臭虫。正如我们所知,DbContext不是线程安全的,两个方法调用都使用相同的OrganizationService实例,该实例本身是使用DatabaseContext的相同实例创建的

这是线程交换环境中实体框架DbContext的局限性。因此,我们使用以下传统方法-

[HttpPost("GetOrganisations")]
public async Task<IActionResult> GetOrganisations([FromBody] GetOrganisationsModel model)
{
    var organisations = 
        await  _organisationService.GetOrganisations(model?.Id, model?.StatusIds);

    var organisationTotalCount = await _organisationService.GetOrganisationCount();

    return Ok(new OrganisationViewModel
    {
        Organisations = organisations,
        OrganisationTotalCount = organisationTotalCount
    });
}
在存储库中更新的缺点是它们紧密耦合,您无法像这样对存储库进行单元测试。如果在特定场景中我必须在Task.whall和单元测试之间进行选择,我将选择单元测试

如果您看到自己经常使用Task.whally,您可能想看看哪些可以与EF一起使用

服务寿命。暂时性窃听

这不是臭虫。正如我们所知,DbContext不是线程安全的,两个方法调用都使用相同的OrganizationService实例,该实例本身是使用DatabaseContext的相同实例创建的

这是线程交换环境中实体框架DbContext的局限性。因此,我们使用以下传统方法-

[HttpPost("GetOrganisations")]
public async Task<IActionResult> GetOrganisations([FromBody] GetOrganisationsModel model)
{
    var organisations = 
        await  _organisationService.GetOrganisations(model?.Id, model?.StatusIds);

    var organisationTotalCount = await _organisationService.GetOrganisationCount();

    return Ok(new OrganisationViewModel
    {
        Organisations = organisations,
        OrganisationTotalCount = organisationTotalCount
    });
}
在存储库中更新的缺点是它们紧密耦合,您无法像这样对存储库进行单元测试。如果在特定场景中我必须在Task.whall和单元测试之间进行选择,我将选择单元测试


如果您经常看到自己在使用Task.when,您可能想看看哪些可以与EF一起使用。

还要注意,在Microsoft依赖项注入中,临时服务在作用域结束之前不会被处理


有一种干净的方法可以解决这个问题,即使用WeakReference作为瞬态,而不是TService。WeakReference的用户随后可以负责Dispose

还要注意,在Microsoft依赖项注入中,临时服务在作用域结束之前不会被释放


有一种干净的方法可以解决这个问题,即使用WeakReference作为瞬态,而不是TService。WeakReference的用户随后可以负责Dispose

啊哈。。好吧。。实际上,我一开始使用wait with WhenAll,但是如果我没有弄错的话,如果没有WhenAll,getOrganizationCount只会在getOrganizations完成后执行,所以。。同步呼叫?只是为了澄清一下,如果使用了wait,那么只有在GetOrganizationCount完成后才会调用GetOrganizationCount。啊哈。。好吧。。实际上,我一开始使用wait with WhenAll,但是如果我没有弄错的话,如果没有WhenAll,getOrganizationCount只会在getOrganizations完成后执行,所以。。同步呼叫?如果使用wait,则仅在GetOrganizationCount完成后才调用GetOrganizationCount,以澄清感谢。
ServiceLifetime.Transient 
public async Task<List<OrganisationEntity>> GetOrganisations(int? organisationId, List<int> statusIds)
{
    var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
    optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(
            "Data Source=.;Initial Catalog=MYDATABASE;Integrated Security=True;Connect Timeout=30;");

    using (var db = new DatabaseContext(optionsBuilder.Options, null))
    {
        IQueryable<OrganisationEntity> organisations =
            db.Organisation.Include(o => o.Status).OrderByDescending(d => d.Created).AsQueryable();

        if (organisationId != null)
        {
            organisations = organisations.Where(o => o.Id == organisationId);
        }

        if (statusIds != null && statusIds.Count > 0)
        {
            organisations = organisations.Where(o => statusIds.Contains(o.StatusId));
        }

        return await organisations.ToListAsync();
    }
}

public async Task<int> GetOrganisationCount()
{
    var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
    optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(
            "Data Source=.;Initial Catalog=MYDATABASE;Integrated Security=True;Connect Timeout=30;");

    using (var db = new DatabaseContext(optionsBuilder.Options, null))
    {
        return await db.Organisation.CountAsync();
    }
}
Task<IEnumerable<OrganisationModel>> organisations = 
    _organisationService.GetOrganisations(model?.Id, model?.StatusIds);

Task<int> organisationTotalCount = _organisationService.GetOrganisationCount();
[HttpPost("GetOrganisations")]
public async Task<IActionResult> GetOrganisations([FromBody] GetOrganisationsModel model)
{
    var organisations = 
        await  _organisationService.GetOrganisations(model?.Id, model?.StatusIds);

    var organisationTotalCount = await _organisationService.GetOrganisationCount();

    return Ok(new OrganisationViewModel
    {
        Organisations = organisations,
        OrganisationTotalCount = organisationTotalCount
    });
}