I'm using Entity Framework
and Multithreading
in a C#
project and I'm experiencing connection problems with SQL Server
.
Well, I wanted to improve the speed of data searches for a grid because they are very time-consuming selects. First I used multithreading in the queries and I saw that it really did not make any difference I trigger queries on different threads because in the database it ends up queuing queries as if I were in a normal loop. To get this resolved, I've started instantiating a number of scopes, repositories, and new connectionstring to each trhead I create, so that he selects them as if they were different people accessing the database and thus running all queries in parallel. It worked, in a way, but when I create many threads in some queries it causes problems like The underlying provider failed on open
and Referência de objeto não definida para uma instância de um objeto
, but it is not always in the same query, it's kind of random. Has anyone ever had such a problem or do you have a solution for it? I am also open to suggestions if there is a better way to do what I am doing. Below is my code:
public void BuscarDadosGridFamilia(string filialSelecionadaCodigo, string familiaSelecionada, string legendaSelecionada)
{
_listaClasseGenericaFamiliaProduto.Clear();
DateTime dataInicialPeriodoVendas = DateTime.Now.AddDays(-30);
DateTime dataFinalPeriodoVendas = DateTime.Now;
_totalVendas30Dias = 0;
_totalEstoqueAtual = 0;
_totalEstoquePrevisto = 0;
_totalCapacidadeMin = 0;
_totalCapacidadeMax = 0;
_totalGiroObj = 0;
decimal _totalGiroAtual = 0;
decimal _totalGiroPrevisto = 0;
decimal _totalGiroCapacidadeMax = 0;
decimal _totalGiroObjetivo = 0;
decimal _totalGiroIdeal = 0;
int _quantidadeTasks = 0;
int _totalLinhasGridFamilia = 0;
string[] filialSplit = filialSelecionadaCodigo.Split('-');
Filial filialSelecionada = _filialAplicacao.RepositorioFilial.ObterPorCodigo(_usuarioAtual.LocalEstoqueAtual.Filial.Empresa, filialSplit[0].Trim());
var _familiaProduto = _familiaProdutoAplicacao.RepositorioFamiliaProduto.Todos()
.Where(d => d.FlagPercentualCapacidadeGondola == 1)
.Where(d => (d.Codigo.StartsWith(familiaSelecionada + ".") || d.Codigo == familiaSelecionada) && familiaSelecionada != "");
if (legendaSelecionada != "Todos")
_familiaProduto = _familiaProduto.Where(d => d.FamiliaMarcadaCapacidadeGondola.LegendaLinha.Legenda == legendaSelecionada.Split('-')[0].Trim());
Task[] tasks = new Task[_familiaProduto.Count()];
foreach (var familia in _familiaProduto)
{
ConexaoBanco.ConexaoMultiThread = "familia-" + familia.Codigo;
string connectionString = ConexaoBanco.GetConexao();
ConexaoBanco.ConexaoMultiThread = "familia-" + familia.Codigo;
IRepositorioEscopo escopo = Havan.Infra.IoC.Container.Obter<IRepositorioEscopo>();
ParametrosTask parametrosTask = new ParametrosTask();
parametrosTask.familia = familia;
parametrosTask.filialSelecionada = filialSelecionada;
parametrosTask.legendaSelecionada = legendaSelecionada;
parametrosTask.repositorioEscopo = escopo;
Task _task = new Task(() => BuscarDadosGridFamiliaTask(parametrosTask), TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
_task.Start();
tasks[_quantidadeTasks] = _task;
_totalLinhasGridFamilia++;
_quantidadeTasks++;
}
Task.WaitAll(tasks);
try { _totalGiroAtual = Arredondar((_totalEstoqueAtual / _totalVendas30Dias) * 30); }
catch (Exception) { Arredondar(_totalGiroAtual = 0); };
try { _totalGiroPrevisto = Arredondar((_totalEstoquePrevisto / _totalVendas30Dias) * 30); }
catch (Exception) { Arredondar(_totalGiroPrevisto = 0); };
try { _totalGiroCapacidadeMax = Arredondar((_totalCapacidadeMax / _totalVendas30Dias) * 30); }
catch (Exception) { Arredondar(_totalGiroCapacidadeMax = 0); };
try { _totalGiroIdeal = Arredondar((_totalVendas30Dias / 30) * _totalGiroObjetivo); }
catch (Exception) { Arredondar(_totalGiroIdeal = 0); };
try { _totalGiroObjetivo = Arredondar(_totalGiroObj / _familiaProduto.Count()); }
catch (Exception) { Arredondar(_totalGiroObjetivo = 0); };
ClasseGenericaFamiliaProduto _classeGenericaFamiliaProdutoTotal = new ClasseGenericaFamiliaProduto();
_classeGenericaFamiliaProdutoTotal.Filial = "TOTAL:";
_classeGenericaFamiliaProdutoTotal.Vendas30Dias = _totalVendas30Dias;
_classeGenericaFamiliaProdutoTotal.EstoqueAtual = _totalEstoqueAtual;
_classeGenericaFamiliaProdutoTotal.EstoquePrevisto = _totalEstoquePrevisto;
_classeGenericaFamiliaProdutoTotal.CapacidadeMin = _totalCapacidadeMin;
_classeGenericaFamiliaProdutoTotal.CapacidadeMax = _totalCapacidadeMax;
_classeGenericaFamiliaProdutoTotal.GiroAtual = _totalGiroAtual;
_classeGenericaFamiliaProdutoTotal.GiroPrevisto = _totalGiroPrevisto;
_classeGenericaFamiliaProdutoTotal.GiroCapacidadeMax = _totalGiroCapacidadeMax;
_classeGenericaFamiliaProdutoTotal.GiroObjetivo = _totalGiroObjetivo;
_classeGenericaFamiliaProdutoTotal.GiroIdeal = _totalGiroIdeal;
if (_listaClasseGenericaFamiliaProduto.Count > 0)
_listaClasseGenericaFamiliaProduto.Add(_classeGenericaFamiliaProdutoTotal);
gridFamilia.DataSource = _listaClasseGenericaFamiliaProduto;
}
And now the method that is called by Tasks
that contains queries to the database by LINQ
public void BuscarDadosGridFamiliaTask(ParametrosTask _parametrosTask)
{
decimal _estoqueSeparadoFamiliaLoja = 0;
decimal _estoqueTransitoFamiliaLoja = 0;
decimal _estoqueEntrarFamiliaLoja = 0;
decimal _estoqueLogicoFamiliaLoja = 0;
decimal _estoquePrevistoFamiliaLoja = 0;
DateTime dataInicialPeriodoVendas = DateTime.Now.AddDays(-30);
DateTime dataFinalPeriodoVendas = DateTime.Now;
_familiaProdutoAplicacao = new FamiliaProdutoAplicacao(_parametrosTask.repositorioEscopo);
_filialAplicacao = new FilialAplicacao(_parametrosTask.repositorioEscopo);
_dadosFamiliaFilialAplicacao = new DadosFamiliaFilialAplicacao(_parametrosTask.repositorioEscopo);
_giroObjetivoFamiliaProdutoAplicacao = new GiroObjetivoFamiliaProdutoAplicacao(_parametrosTask.repositorioEscopo);
_saldoEstoqueProdutoAplicacao = new SaldoEstoqueProdutoAplicacao(_parametrosTask.repositorioEscopo);
_resumoVendasAplicacao = new ResumoVendasAplicacao(_parametrosTask.repositorioEscopo);
_legendaLinhaAplicacao = new LegendaLinhaAplicacao(_parametrosTask.repositorioEscopo);
_wrkGenerico01Aplicacao = new WrkGenerico01Aplicacao(_parametrosTask.repositorioEscopo);
_parametroClasseABCFamiliaAplicacao = new ParametroClasseABCFamiliaAplicacao(_parametrosTask.repositorioEscopo);
_usuarioAtualAplicacao = new UsuarioAplicacao(_parametrosTask.repositorioEscopo);
Int64 _idPrimeiroNivelFamilia = _familiaProdutoAplicacao.RepositorioFamiliaProduto.ObterPorCodigo(_parametrosTask.familia.Codigo.Split('.')[0]).FirstOrDefault().Id;
ParametroClasseABCFamilia _parametroClasseABCFamilia = _parametroClasseABCFamiliaAplicacao.ParametroClasseABCFamiliaPorFamiliaClasse(_parametrosTask.filialSelecionada.Id, _idPrimeiroNivelFamilia).FirstOrDefault();
ClasseGenericaFamiliaProduto _classeGenericaFamiliaProduto = new ClasseGenericaFamiliaProduto();
_saldoEstoqueProdutoAplicacao.ObterSaldoEstoqueProdutosFamilia(_usuarioAtual.TipoEstoque.Id, _parametrosTask.filialSelecionada, _parametrosTask.familia.Codigo, true, out _estoqueLogicoFamiliaLoja, false, out _estoqueSeparadoFamiliaLoja, false, out _estoqueTransitoFamiliaLoja, false, out _estoqueEntrarFamiliaLoja, true, out _estoquePrevistoFamiliaLoja);
_classeGenericaFamiliaProduto.Filial = _parametrosTask.filialSelecionada.Codigo + " - " + _parametrosTask.filialSelecionada.Apelido;
try { _classeGenericaFamiliaProduto.LinhaProduto = _parametrosTask.familia.FamiliaMarcadaCapacidadeGondola.LegendaLinha.Descricao; }
catch (Exception) { _classeGenericaFamiliaProduto.LinhaProduto = ""; };
_classeGenericaFamiliaProduto.Familia = _parametrosTask.familia.Codigo;
_classeGenericaFamiliaProduto.DescricaoFamilia = _parametrosTask.familia.Nome;
try { _classeGenericaFamiliaProduto.Vendas30Dias = Arredondar((decimal)_resumoVendasAplicacao.RepositorioResumoVendas.ObterQuantidadeVendaPorFamiliaFilial(_parametrosTask.filialSelecionada.Id, _parametrosTask.familia.Id, dataInicialPeriodoVendas, dataFinalPeriodoVendas)); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.Vendas30Dias = 0); };
_totalVendas30Dias += Arredondar(_classeGenericaFamiliaProduto.Vendas30Dias);
_classeGenericaFamiliaProduto.EstoqueAtual = Arredondar(_estoqueLogicoFamiliaLoja);
_totalEstoqueAtual += Arredondar(_classeGenericaFamiliaProduto.EstoqueAtual);
_classeGenericaFamiliaProduto.EstoquePrevisto = Arredondar(_estoquePrevistoFamiliaLoja);
_totalEstoquePrevisto += Arredondar(_classeGenericaFamiliaProduto.EstoquePrevisto);
_classeGenericaFamiliaProduto.CapacidadeMin = Arredondar(_dadosFamiliaFilialAplicacao.RepositorioDadosFamiliaFilial.ObterLimiteMaximoFamiliaEstoque(_familiaProdutoAplicacao.RepositorioFamiliaProduto, _usuarioAtual.LocalEstoqueAtual.Filial.Empresa.Id, _usuarioAtual.TipoEstoque.Id, _parametrosTask.familia.FamiliaMarcadaCapacidadeGondola.Codigo, _parametrosTask.familia.Codigo, _parametrosTask.filialSelecionada.Id).Select(d => d.Quantidade).FirstOrDefault());
_totalCapacidadeMin += Arredondar(_classeGenericaFamiliaProduto.CapacidadeMin);
try { _classeGenericaFamiliaProduto.CapacidadeMax = Arredondar(_familiaProdutoAplicacao.CalculoEstoqueMaximoFamilia(_classeGenericaFamiliaProduto.CapacidadeMin, _classeGenericaFamiliaProduto.Vendas30Dias, _parametrosTask.filialSelecionada.TempoReposicaoEmDias, _parametroClasseABCFamilia.FatorClasseFamilia, _parametroClasseABCFamilia.PercentualCabideFamilia)); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.CapacidadeMax = 0); };
_totalCapacidadeMax += Arredondar(_classeGenericaFamiliaProduto.CapacidadeMax);
try { _classeGenericaFamiliaProduto.GiroAtual = Arredondar((_classeGenericaFamiliaProduto.EstoqueAtual / _classeGenericaFamiliaProduto.Vendas30Dias) * 30); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.GiroAtual = 0); };
try { _classeGenericaFamiliaProduto.GiroPrevisto = Arredondar((_classeGenericaFamiliaProduto.EstoquePrevisto / _classeGenericaFamiliaProduto.Vendas30Dias) * 30); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.GiroPrevisto = 0); };
try { _classeGenericaFamiliaProduto.GiroCapacidadeMax = Arredondar((_classeGenericaFamiliaProduto.CapacidadeMax / _classeGenericaFamiliaProduto.Vendas30Dias) * 30); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.GiroCapacidadeMax = 0); };
_classeGenericaFamiliaProduto.GiroObjetivo = Arredondar(_giroObjetivoFamiliaProdutoAplicacao.BuscaGiroObjetivoFamiliaMaisProxima(_parametrosTask.familia.Codigo, _parametrosTask.filialSelecionada.Id));
_totalGiroObj += Arredondar(_classeGenericaFamiliaProduto.GiroObjetivo);
try { _classeGenericaFamiliaProduto.GiroIdeal = Arredondar((_classeGenericaFamiliaProduto.Vendas30Dias / 30) * _classeGenericaFamiliaProduto.GiroObjetivo); }
catch (Exception) { Arredondar(_classeGenericaFamiliaProduto.GiroIdeal = 0); };
_classeGenericaFamiliaProduto.NecessidadeGiro = (Arredondar(_classeGenericaFamiliaProduto.GiroIdeal - _classeGenericaFamiliaProduto.EstoquePrevisto) < 0 ? 0 : Arredondar(_classeGenericaFamiliaProduto.GiroIdeal - _classeGenericaFamiliaProduto.EstoquePrevisto));
_classeGenericaFamiliaProduto.NecessidadeCapacidade = (Arredondar(_classeGenericaFamiliaProduto.CapacidadeMax - _classeGenericaFamiliaProduto.EstoquePrevisto) < 0 ? 0 : Arredondar(_classeGenericaFamiliaProduto.CapacidadeMax - _classeGenericaFamiliaProduto.EstoquePrevisto));
try { _classeGenericaFamiliaProduto.SGiro = Formatar((_classeGenericaFamiliaProduto.GiroPrevisto / _classeGenericaFamiliaProduto.GiroObjetivo) * 100); }
catch (Exception) { Formatar(_classeGenericaFamiliaProduto.SGiro = 0); };
_listaClasseGenericaFamiliaProduto.Add(_classeGenericaFamiliaProduto);
}