SqlComplexOperations 1.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package SqlComplexOperations --version 1.0.1
                    
NuGet\Install-Package SqlComplexOperations -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SqlComplexOperations" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SqlComplexOperations" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="SqlComplexOperations" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SqlComplexOperations --version 1.0.1
                    
#r "nuget: SqlComplexOperations, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SqlComplexOperations@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SqlComplexOperations&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=SqlComplexOperations&version=1.0.1
                    
Install as a Cake Tool

SqlComplexOperations

Objetivo

Quando precisamos processar uma quantidade significativa de dados em uma aplicação, por vezes executar de forma unitária cada registro pode não ser a melhor saída. <br><br> O projeto foi criado com o objetivo de contornar este problema, possibilitando uma forma de processamento mais eficaz utilizando comandos existentes no SqlServer e no .Net.

Estrutura do projeto

  • Component: Possui a implementação da biblioteca em si.

  • Poc: Possui projetos utilizando a implementação principal para testes e validações.

  • Bench: Possui o projeto que realiza benchmarks utilizando a abordagem proposta e implementações tradicionais.

Guia de uso

Com a biblioteca referenciada em seu projeto, realize a injeção da mesma utilizando o método ConfigureMergeBuilder:

builder.Services.ConfigureSqlComplexOperations();

Com o serviço injetado, já podemos configurar o builder para posteriormente executarmos a intrução no banco de dados. Exemplo abaixo utilizando uma classe de exemplo "Fornecedor":

var builder = await _mergeBuilder.Create<Fornecedor>()
    .SetDataSource(dataSource)
    .SetMergeColumns(x => x.Documento)
    .SetUpdatedColumns(x => x)
    .SetTransaction(transaction.GetDbTransaction())
    .UseSnakeCaseNamingConvention()
    .WithCondition(ConditionTypes.NOT_EQUAL, ConditionOperator.OR, x => new { x.Cep, x.Nome })
    .SetIgnoreOnIsertOperation(x => x.Id)
    .UseEnumStatusConfiguration(x => x.Status)
    .Execute();

Após configurar todos os parâmetros desejados, basta invocar o método Execute.

Parâmetros

Pare configurar o builder, os possuímos os parâmetros:

  • SetDataSource [obrigatório]:

    • Lista de objetos que deseja adicionar, mesclar ou atualizar no banco de dados. Deve possuir a mesma estrutura da tabela do banco.

      .SetDataSource(dataSource)
      
  • SetMergeColumns [obrigatório]:

    • Lista de campos que deseja utilizar para comparar se o mesmo existe ou não na tabela de destino.

    • Caso as colunas comparadas existam, o comando entenderá uma atualização. Caso contrário, um novo registro será inserido.

    • Uma ou mais colunas podem ser configuradas, desde que elas existam na entidade configurada.

      .SetMergeColumns(x => x.Documento)
      
  • SetUpdatedColumns [obrigatório]:

    • Colunas que serão afetadas no caso de uma atualização na tabela de destino.

    • Podemos configurar para executar em todas:

      .SetUpdatedColumns(x => x)
      
    • Podemos também configurar as colunas individualmente, sendo uma ou várias:

      .SetUpdatedColumns(x => new { x.Cep, x.Nome } )
      
  • SetTransaction [obrigatório]:

    • Precisamos disponibilizar uma transação para a biblioteca realizar o comando no banco de dados.

    • Ao realizar a operação, você precisa realizar o commit no banco de dados para efetivar as alterações.

      .SetTransaction(transaction.GetDbTransaction())  
      
  • WithCondition [opcional]:

    • Podemos configurar condições para o comando só realizar as alterações em registros existentes e que realmente sofreram alterações.

    • Antes de realizar o update, o comando checa se os campos que você deseja comparar estão diferentes entre o data source e a tabela de destino, evitando processamento desnecessário no banco de dados.

    • As condições devem ser configuradas citando um tipo de operação - quanto utilizada mais de uma coluna - (AND ou OR) e o tipo de comparação (EQUAL ou NOT_EQUAL).

    • Exemplo utilizando uma comparação NOT_EQUAL em duas colunas com instrução OU:

         .WithCondition(ConditionTypes.NOT_EQUAL, ConditionOperator.OR, x => new { x.Cep, x.Nome })
      
    • Exemplo utilizando uma comparação EQUAL em uma coluna:

         .WithCondition(ConditionTypes.EQUALS, x => x.Nome)
      
  • SetIgnoreOnIsertOperation [opcional]:

    • Podemos configurar colunar que são ignoradas ao realizar a instrução de inserção, como por exemplo campos auto identity ou colunas que você simplesmente não queira utilizar na inserção do registro.

      .SetIgnoreOnIsertOperation(x => x.Id)
      
  • UseStatusConfiguration [opcional]:

    • Utilize uma coluna de status em sua tabela de destino para receber a informação se, após a execução do comando merge, o registro foi alterado, inserido ou simplesmente não foi afetado.

      .UseStatusConfiguration(x => x.Status)
      
  • UseEnumStatusConfiguration [opcional]:

    • Mesmo objetivo do parâmetro UseStatusConfiguration, porém utiliza como status em sua coluna de destino o enumerador fornecido pela bibliotea, tratando-o como tipo int no banco de dados.

    • Enum BulkStatus

      PROCESSADO = 0,
      ALTERADO = 1,
      INSERIDO = 2
      
      .UseStatusConfiguration(x => x.Status)
      
  • UseSnakeCaseNamingConvention [opcional]:

    • Caso utilize em seu banco de dados alguma convensão específica, a biblioteca da suporte a:
      • UseSnakeCaseNamingConvention

        .UseSnakeCaseNamingConvention()
        

Benchmarks

Processamento de 1000 registros (realizando o update em 100% dos registros)

//|         Method |       Mean |      Error |     StdDev |     Median |
//|--------------- |-----------:|-----------:|-----------:|-----------:|
//| UpdateOneByOne | 9,374.0 ms | 4,796.4 ms | 1,245.6 ms | 8,974.7 ms |
//|         Upsert |   640.1 ms | 3,296.8 ms |   856.2 ms |   283.1 ms |

Processamento de 1000 registros (realizando o update em 40% dos registros, descartando 60% de dados inalterados)

//|          Method |       Mean |      Error |   StdDev |     Median |
//|---------------- |-----------:|-----------:|---------:|-----------:|
//| ExecuteOneByOne | 4,371.5 ms | 2,710.0 ms | 703.8 ms | 4,487.3 ms |
//|   ExecuteUpsert |   512.2 ms | 2,610.2 ms | 677.9 ms |   214.0 ms |

Processamento de 1000 registros (500 registros novos, 200 updates e 300 descartados)

//|          Method |        Mean |      Error |     StdDev |      Median |
//|---------------- |------------:|-----------:|-----------:|------------:|
//| ExecuteOneByOne | 11,393.5 ms | 6,724.8 ms | 4,448.0 ms | 11,230.3 ms |
//|   ExecuteUpsert |    498.7 ms |   931.6 ms |   616.2 ms |    299.2 ms |

Processamento de 1000 registros (500 registros novos, 200 updates e 300 descartados) (minimizando queries de busca no banco)

//|          Method |       Mean |      Error |   StdDev |     Median |
//|---------------- |-----------:|-----------:|---------:|-----------:|
//| ExecuteOneByOne | 3,492.1 ms | 3,190.9 ms | 828.7 ms | 3,690.2 ms |
//|   ExecuteUpsert |   492.3 ms | 2,404.4 ms | 624.4 ms |   216.1 ms |

Processamento de 1000 registros (500 registros novos, 200 updates e 300 descartados) (minimizando queries de busca no banco e insert unico no processamento sem bulk)

|          Method |       Mean |      Error |     StdDev |     Median |
|---------------- |-----------:|-----------:|-----------:|-----------:|
| ExecuteOneByOne | 4,793.3 ms | 2,808.9 ms | 1,857.9 ms | 4,215.0 ms |
|   ExecuteUpsert |   508.5 ms | 1,032.9 ms |   683.2 ms |   278.3 ms |    
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 2,863 11/3/2025
2.0.1 131 10/31/2025
2.0.0 16,130 12/9/2024
1.0.1 2,014 11/13/2024
1.0.0 162 11/8/2024

Adiciona virtual nos metodos Execute das operações para facilitar os testes de unidade.
Adiciona documentação.