DbContext 和任务

DbContext and Task

我们发现一些难以重现的问题似乎与 SQL 服务器以及我们如何与它通信有关,我正在调查我们是否可能将 DBContext 与 Task 错误结合使用。

我们有一个 signalR 集线器用于我的许多不同的客户端。当我们达到一定级别的客户端时,系统会变慢,最终会停止工作。

signalR 与此示例类似,但具有更多异步方法:

namespace Test.Webservice.Hubs
{
    public class ExampleHub : Hub<ExampleClientContract>, IExampleHub
    {
        private readonly ILogger _logger;
        private readonly IExampleRepository _exampleRepo;

        public ExampleHub(ILogger logger, IExampleRepository exampleRepo)
        {
            _logger = logger;
            _exampleRepo = exampleRepo;
        }
        
        public async Task<IEnumerable<ExampleTopicState>> GetExampleStates(Guid operationId)
        {
            var examples = await _exampleRepo.GetExampleStatesAsync(operationId);

            return examples.Select(ExampleTopicState.Create);
        }   
    }
} 

ExampleRepository 看起来像这样,但同样有更多的方法:

namespace Test.DataAccess.Repository
{
    public class ExampleRepository : IExampleRepository
    {
        private readonly ILogger _logger;
        private readonly ExampleContext _context;
        private readonly IExampleRepositoryMapping _repositoryMapping;

        public ExampleRepository(ILogger logger, IExampleRepositoryMapping repositoryMapping)
        {
            _repositoryMapping = repositoryMapping;
            _logger = logger;
            _context = new ExampleContext();
        }

        public async Task<IEnumerable<ExampleDto>> GetExampleStatesAsync(Guid operationId)
        {
            IEnumerable<Example> result = null;

            await Task.Factory.StartNew(() =>
                                        {
                                            result = _context
                                                     .Examples.Where(c => c.OperationId.Equals(operationId))
                                                     .GroupBy(o => o.Type)
                                                     .SelectMany(p => p.GroupBy(q => q.Topic))
                                                     .Select(o => o.FirstOrDefault(
                                                                 n => n.ExampleTimeUtc == o.Max(d => d.ExampleTimeUtc)));
                                        });

            return _repositoryMapping.Mapper.Map<IEnumerable<ExampleDto>>(result);
        }

    }
}

在 wait Task.Factory.StartNew 中使用 DbContext 是否正确,或者这会导致问题吗? This SO answere好像是说可能有问题,但我不确定自己是否完全理解。

编辑:

Thought id 添加有关如何从其中一个客户端调用集线器的示例:

    var loadingTasks = _connectorMap.Select(o => (System.Action) ( () =>
                                                                        {
                                                                            var result =  o.Proxy.Invoke<ExampleResult>(
                                                                                "GetExampless",
                                                                                _connectedOperations.Where(c => o.HubConnection.Url.StartsWith(c.ExampleWebService)).Select(s => s.UniqueId),
                                                                                filter.TimeFilter.Start,
                                                                                filter.TimeFilter.End,
                                                                                filter.TopicFilter,
                                                                                filter.SeverityLevelFilter,
                                                                                currentPage, pageSize,
                                                                                filter.IsGrouped).Result;
                                                                            _results.Add(result);
                                                                        }));

    Parallel.ForEach(loadingTasks, lt => lt());

您只需要 SelectAsync 吗?

public async Task<IEnumerable<ExampleDto>> GetExampleStatesAsync(Guid operationId)
{
    IEnumerable<Example> result = null;

    var result = await _context
            ...
            .SelectMany(...);
            .Select(...)
            .ToListAsync(); // Fetch from db.
    });

    return _repositoryMapping.Mapper.Map<IEnumerable<ExampleDto>>(result);
}

Async query and save.

提供了完整示例