Working with Entity Framework, Multithreading and SQL Server in C #

0

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);
}
    
asked by anonymous 13.10.2014 / 21:14

1 answer

1

This here:

_familiaProdutoAplicacao.RepositorioFamiliaProduto.Todos()

It sucks in every way for performance, since you make a TABLE SCAN for each query. Here I explain why using repository with Entity Framework is not worth .

The second thing that caught my attention is how many queries you make to synthesize information. I do not know how your code is under this, but it's very likely that the same information will be brought in several times. The fuller the context (which in your case is shared), the slower it gets. Here in this answer I teach how to optimize the context for large pieces of data , but I think the gain will be small because of the way your application was built.

I suggest rethinking all this architecture. I can help if you give more details of your LINQ queries.

    
13.10.2014 / 21:24