DbContext and Task

We are seeing some hard to reproduce issues that seem to relate to the SQL server and how we communicate with it, and I’m investigating if we might be using DBContext in conjunction with Task wrong.

We have a signalR hub used my many different clients. When we reach a certain level of clients, the system slows down and things will eventually stop working.

The signalR is similar to this example, but with many more async methods:

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);
        }   
    }
}

The ExampleRepository looks something like this, but again with many more methods:

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);
        }

    }
}

Is it correct to use DbContext inside wait Task.Factory.StartNew, or could this lead to issues? This SO answere seems to say that it could be problematic, but I’m not sure if I understand it fully.

Edit:

Thought id add en example on how the hub is called from one of the clients:

    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());

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Do you just want 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);
}

A full example is available at Async query and save.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x