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);
}
提供了完整示例
我们发现一些难以重现的问题似乎与 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);
}
提供了完整示例