diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9be589b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# EditorConfig for Codout.Framework +# https://editorconfig.org +# +# Repository convention: all text files are UTF-8 with LF line endings and a +# trailing newline. Honored by Visual Studio, VS Code, JetBrains Rider, and +# any editor with EditorConfig support. + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true + +# Windows-only batch/cmd scripts must stay CRLF. +[*.{cmd,bat}] +end_of_line = crlf diff --git a/.gitattributes b/.gitattributes index 1ff0c42..f86df03 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,10 @@ ############################################################################### -# Set default behavior to automatically normalize line endings. +# Set default behavior to automatically normalize line endings to LF on commit. +# Repository convention is UTF-8 + LF for all text files. Encoding itself is +# enforced via .editorconfig (charset = utf-8); .gitattributes only handles +# line endings here. ############################################################################### -* text=auto +* text=auto eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/release-packages.json b/.github/release-packages.json new file mode 100644 index 0000000..2839bfd --- /dev/null +++ b/.github/release-packages.json @@ -0,0 +1,29 @@ +{ + "dynamiclinq": "Codout.DynamicLinq/Codout.DynamicLinq.csproj", + "api": "Codout.Framework.Api/Codout.Framework.Api.csproj", + "api-client": "Codout.Framework.Api.Client/Codout.Framework.Api.Client.csproj", + "api-dto": "Codout.Framework.Api.Dto/Codout.Framework.Api.Dto.csproj", + "application": "Codout.Framework.Application/Codout.Framework.Application.csproj", + "common": "Codout.Framework.Common/Codout.Framework.Common.csproj", + "dp": "Codout.Framework.DP/Codout.Framework.DP.csproj", + "data": "Codout.Framework.Data/Codout.Framework.Data.csproj", + "domain": "Codout.Framework.Domain/Codout.Framework.Domain.csproj", + "ef": "Codout.Framework.EF/Codout.Framework.EF.csproj", + "mongo": "Codout.Framework.Mongo/Codout.Framework.Mongo.csproj", + "nh": "Codout.Framework.NH/Codout.Framework.NH.csproj", + "storage": "Codout.Framework.Storage/Codout.Framework.Storage.csproj", + "storage-azure": "Codout.Framework.Storage.Azure/Codout.Framework.Storage.Azure.csproj", + "image-extensions": "Codout.Image.Extensions/Codout.Image.Extensions.csproj", + "mailer": "Codout.Mailer/Codout.Mailer.csproj", + "mailer-aws": "Codout.Mailer.AWS/Codout.Mailer.AWS.csproj", + "mailer-razor": "Codout.Mailer.Razor/Codout.Mailer.Razor.csproj", + "mailer-sendgrid": "Codout.Mailer.SendGrid/Codout.Mailer.SendGrid.csproj", + "multitenancy": "Codout.Multitenancy/Codout.Multitenancy.csproj", + "softprime-multitenancy": "Codout.Multitenancy/Softprime.Multitenancy.csproj", + "cosmos": "src/NetCore/Codout.Framework.NetCore.Repository.Cosmos/Codout.Framework.NetCore.Repository.Cosmos.csproj", + "documentdb": "src/NetCore/Codout.Framework.NetCore.Repository.DocumentDB/Codout.Framework.NetCore.Repository.DocumentDB.csproj", + "security-argon2": "src/Security/Codout.Security.Argon2/Codout.Security.Argon2.csproj", + "security-bcrypt": "src/Security/Codout.Security.Bcrypt/Codout.Security.Bcrypt.csproj", + "security-core": "src/Security/Codout.Security.Core/Codout.Security.Core.csproj", + "security-scrypt": "src/Security/Codout.Security.Scrypt/Codout.Security.Scrypt.csproj" +} diff --git a/.github/workflows/mass-release.yml b/.github/workflows/mass-release.yml new file mode 100644 index 0000000..ebe169b --- /dev/null +++ b/.github/workflows/mass-release.yml @@ -0,0 +1,131 @@ +name: Mass Release + +# One-shot workflow to publish every Codout.Framework package at the +# currently pinned in its .csproj. Designed for the initial baseline release +# after migrating to per-package versions (where most packages are at 6.2.2 +# and Codout.Framework.EF is at 6.3.0). Idempotent thanks to --skip-duplicate, +# so it is safe to re-run. +# +# Recommended flow: +# 1. Dispatch with dry_run = true to confirm the package list and artifacts. +# 2. Re-dispatch with dry_run = false to publish. + +on: + workflow_dispatch: + inputs: + confirm: + description: 'Type PUBLISH to confirm. Anything else is rejected.' + required: true + include_mcp: + description: 'Also release Codout.Framework.Mcp (otherwise excluded; use mcp-release.yml).' + type: boolean + default: false + dry_run: + description: 'Build and pack only; do not push to NuGet.org.' + type: boolean + default: true + +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + CONFIGURATION: Release + MAPPING: .github/release-packages.json + MCP_PROJECT: Codout.Framework.Mcp/src/Tools/Codout.Framework.Mcp/Codout.Framework.Mcp.csproj + +jobs: + mass-release: + runs-on: ubuntu-latest + if: inputs.confirm == 'PUBLISH' + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + + - name: Verify dispatched from master + run: | + set -euo pipefail + git fetch origin master --quiet + if ! git merge-base --is-ancestor HEAD origin/master; then + echo "::error::Mass release must be dispatched from a commit on master." + echo "Currently at $(git rev-parse HEAD); origin/master tip is $(git rev-parse origin/master)." + exit 1 + fi + echo "Dispatched from a commit on master: OK" + + - name: Restore + build + test (solution) + run: | + dotnet restore Codout.Framework.sln + dotnet build Codout.Framework.sln --configuration "$CONFIGURATION" --no-restore + dotnet test Codout.Framework.sln --configuration "$CONFIGURATION" --no-build --verbosity normal + + - name: Pack every package + run: | + set -euo pipefail + mkdir -p ./artifacts + + # Out-of-solution projects (Cosmos, DocumentDB, etc.) need their own + # restore/build, so we deliberately do NOT pass --no-build here. + for pkg in $(jq -r 'keys[]' "$MAPPING"); do + project=$(jq -r --arg p "$pkg" '.[$p]' "$MAPPING") + echo "::group::Pack $pkg ($project)" + dotnet pack "$project" --configuration "$CONFIGURATION" --output ./artifacts + echo "::endgroup::" + done + + if [ "${{ inputs.include_mcp }}" = "true" ]; then + echo "::group::Pack mcp ($MCP_PROJECT)" + dotnet pack "$MCP_PROJECT" --configuration "$CONFIGURATION" --output ./artifacts + echo "::endgroup::" + fi + + echo "Generated artifacts:" + ls -la ./artifacts + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: codout-framework-all-nupkg + path: ./artifacts/*.nupkg + if-no-files-found: error + + - name: Push to NuGet.org + if: inputs.dry_run != true + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: | + set -euo pipefail + if [ -z "${NUGET_API_KEY:-}" ]; then + echo "::error::NUGET_API_KEY secret is not set; aborting." + exit 1 + fi + # --skip-duplicate makes this idempotent: re-runs will not fail on + # already-published versions. + dotnet nuget push "./artifacts/*.nupkg" \ + --api-key "$NUGET_API_KEY" \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate + + - name: Summary + if: always() + run: | + { + echo "## Mass release summary" + echo "" + echo "- Dry run: \`${{ inputs.dry_run }}\`" + echo "- Mcp included: \`${{ inputs.include_mcp }}\`" + echo "" + echo "### Packed artifacts" + echo "" + echo '```' + ls -1 ./artifacts 2>/dev/null || echo "(no artifacts directory)" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9950cc5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,170 @@ +name: Package Release + +# Generic release workflow for the Codout.Framework packages, one package at a +# time. Mapping from short name to .csproj lives in .github/release-packages.json. +# +# Trigger by pushing a tag in the form "-v", e.g. "ef-v6.3.0", +# "mongo-v6.2.3", "mailer-razor-v6.2.2". The Codout.Framework.Mcp package keeps +# its own dedicated workflow (mcp-release.yml), so "mcp-v*" tags are excluded +# here to avoid a double release. +# +# workflow_dispatch builds and packs without publishing, useful for smoke- +# testing a package locally before tagging. + +on: + push: + tags: + - '*-v*.*.*' + - '!mcp-v*' + workflow_dispatch: + inputs: + package: + description: 'Package short name (see .github/release-packages.json).' + type: string + required: true + version: + description: 'Optional version override (e.g. 6.3.1). Leave empty to use the from the .csproj.' + required: false + +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + CONFIGURATION: Release + MAPPING: .github/release-packages.json + +jobs: + build-pack: + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + package: ${{ steps.resolve.outputs.package }} + project: ${{ steps.resolve.outputs.project }} + version: ${{ steps.resolve.outputs.version }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # Full history so the master-ancestry gate can resolve merge-base. + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + + - name: Verify tag is on master + if: startsWith(github.ref, 'refs/tags/') + run: | + set -euo pipefail + git fetch origin master --quiet + if ! git merge-base --is-ancestor HEAD origin/master; then + echo "::error::Tag '${GITHUB_REF_NAME}' is not an ancestor of origin/master." + echo "Releases must be cut from commits that have been merged into master." + exit 1 + fi + echo "Tag '${GITHUB_REF_NAME}' is on master: OK" + + - name: Resolve package and version + id: resolve + run: | + set -euo pipefail + if [ -n "${{ github.event.inputs.package }}" ]; then + PKG="${{ github.event.inputs.package }}" + VERSION="${{ github.event.inputs.version }}" + else + TAG="${GITHUB_REF#refs/tags/}" + PKG="${TAG%-v*}" + VERSION="${TAG##*-v}" + fi + + PROJECT=$(jq -r --arg p "$PKG" '.[$p] // empty' "$MAPPING") + if [ -z "$PROJECT" ]; then + echo "::error::Unknown package '$PKG'." + echo "Known packages:" + jq -r 'keys[]' "$MAPPING" | sed 's/^/ - /' + exit 1 + fi + if [ ! -f "$PROJECT" ]; then + echo "::error::Mapped project not found on disk: $PROJECT" + exit 1 + fi + + echo "package=$PKG" | tee -a "$GITHUB_OUTPUT" + echo "project=$PROJECT" | tee -a "$GITHUB_OUTPUT" + echo "version=$VERSION" | tee -a "$GITHUB_OUTPUT" + + # Build + test the whole solution as a safety net. The solution currently + # has no tests registered in it (tests live in side projects with external + # infra dependencies, see appsettings.json), so `dotnet test` here is a + # no-op today and will pick up tests automatically once they are added. + - name: Restore (solution) + run: dotnet restore Codout.Framework.sln + + - name: Build (solution) + run: dotnet build Codout.Framework.sln --configuration "$CONFIGURATION" --no-restore + + - name: Test (solution) + run: dotnet test Codout.Framework.sln --configuration "$CONFIGURATION" --no-build --verbosity normal + + - name: Pack + run: | + set -euo pipefail + VERSION="${{ steps.resolve.outputs.version }}" + PROJECT="${{ steps.resolve.outputs.project }}" + # Pack performs its own restore/build for the target. Some packages + # (Cosmos, DocumentDB, etc.) are not part of Codout.Framework.sln, so + # we deliberately do NOT pass --no-build here. + if [ -n "$VERSION" ]; then + dotnet pack "$PROJECT" --configuration "$CONFIGURATION" \ + -p:Version="$VERSION" \ + -p:PackageVersion="$VERSION" \ + --output ./artifacts + else + dotnet pack "$PROJECT" --configuration "$CONFIGURATION" \ + --output ./artifacts + fi + ls -la ./artifacts + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.resolve.outputs.package }}-nupkg + path: ./artifacts/*.nupkg + if-no-files-found: error + + publish: + needs: build-pack + runs-on: ubuntu-latest + # Only push to NuGet for real release tags. workflow_dispatch (manual) runs + # are build/pack-only smoke tests. + if: startsWith(github.ref, 'refs/tags/') + permissions: + contents: read + + steps: + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ needs.build-pack.outputs.package }}-nupkg + path: ./artifacts + + - name: Push to NuGet.org + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: | + set -euo pipefail + if [ -z "${NUGET_API_KEY:-}" ]; then + echo "::error::NUGET_API_KEY secret is not set; aborting." + exit 1 + fi + dotnet nuget push "./artifacts/*.nupkg" \ + --api-key "$NUGET_API_KEY" \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate diff --git a/CHANGELOG.md b/CHANGELOG.md index b690da0..d252608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,22 +5,44 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +A partir desta entrada cada pacote NuGet é versionado individualmente +(`` declarado em cada `.csproj` em vez de centralizado em +`Directory.Build.props`). As entradas abaixo identificam o pacote e a +versão afetados. + +## 2026-05-12 + +### Build + +- **Repositório** — `` removido de `Directory.Build.props` e movido para cada `.csproj` publicável. Cada pacote agora evolui independentemente; alterações em um pacote não disparam mais um build novo dos demais. Pacotes que não tiveram alteração ficaram congelados em `6.2.2`. + +### Codout.Framework.EF 6.3.0 + +#### Fixed +- `EFRepository.SaveOrUpdate` / `SaveOrUpdateAsync` decidiam insert vs. update via `IEntity.IsTransient()`, o que quebrava qualquer entidade que pré-atribuísse o `Id` no construtor (ex.: `Id = Guid.NewGuid()`). A entidade era marcada como `Modified` e o `SaveChanges` falhava ao tentar `UPDATE` em uma linha inexistente. Agora a decisão é feita inspecionando `Context.Entry(entity).State` e, para entidades `Detached` com chave atribuída, consultando o banco via `Find` / `FindAsync`. +- `SaveOrUpdateAsync` deixou de bloquear a thread chamando `Find` síncrono; agora usa `FindAsync` e respeita o `CancellationToken` recebido. +- Quando o `SaveOrUpdate` precisa atualizar uma entidade existente, os valores são copiados via `Entry(existing).CurrentValues.SetValues(entity)`, preservando os `OriginalValues` (e portanto tokens de concorrência como `[Timestamp]`/`RowVersion`) trazidos do banco. + +#### Changed +- `SaveOrUpdate` em entidade já rastreada com estado `Unchanged` não força mais a transição para `Modified`. Confia no change tracker para detectar mutações. Consumidores que dependiam do "force full update" devem chamar `Update(entity)` explicitamente. +- `SaveOrUpdate` em entidade `Detached` com chave não-default agora executa um roundtrip ao banco (`Find` / `FindAsync`) para distinguir insert de update. Em hot paths onde a intenção é conhecida, prefira `Save(entity)` ou `Update(entity)` para evitar a query. + ## [6.2.0] - 2025-07-17 ### Added -- **Codout.Mailer.Razor** � novo pacote sat�lite que implementa `ITemplateEngine` usando a engine Razor nativa do ASP.NET Core (`IRazorViewEngine` + `RuntimeCompilation` + `EmbeddedFileProvider`). +- **Codout.Mailer.Razor** — novo pacote satélite que implementa `ITemplateEngine` usando a engine Razor nativa do ASP.NET Core (`IRazorViewEngine` + `RuntimeCompilation` + `EmbeddedFileProvider`). - Extension method `AddMailerRazor()` para registro do template engine Razor via DI. -- Classe `RazorMailerOptions` com op��es `TemplateAssembly`, `RootNamespace` e `EnableCache`. +- Classe `RazorMailerOptions` com opções `TemplateAssembly`, `RootNamespace` e `EnableCache`. ### Changed -- **Codout.Mailer** � o core agora � agn�stico ao template engine. A interface `ITemplateEngine` permanece, mas nenhuma implementa��o � registrada automaticamente. -- `AddMailer()` n�o registra mais `ITemplateEngine` por padr�o � o consumidor deve registrar via `AddMailerRazor()` ou implementa��o pr�pria. -- `MailerOptions` simplificado � removidas propriedades `TemplateRootType`, `RazorLight` e a classe `RazorLightOptions`. -- Depend�ncias `Microsoft.Extensions.*` agora s�o referenciadas explicitamente no `Codout.Mailer.csproj` (antes eram transitivas via RazorLight). +- **Codout.Mailer** — o core agora é agnóstico ao template engine. A interface `ITemplateEngine` permanece, mas nenhuma implementação é registrada automaticamente. +- `AddMailer()` não registra mais `ITemplateEngine` por padrão — o consumidor deve registrar via `AddMailerRazor()` ou implementação própria. +- `MailerOptions` simplificado — removidas propriedades `TemplateRootType`, `RazorLight` e a classe `RazorLightOptions`. +- Dependências `Microsoft.Extensions.*` agora são referenciadas explicitamente no `Codout.Mailer.csproj` (antes eram transitivas via RazorLight). ### Removed -- **RazorLight** � removida depend�ncia do pacote `RazorLight 2.3.1` do core `Codout.Mailer`. -- Classe `RazorTemplateEngine` removida do core (substitu�da por `RazorViewTemplateEngine` no pacote `Codout.Mailer.Razor`). +- **RazorLight** — removida dependência do pacote `RazorLight 2.3.1` do core `Codout.Mailer`. +- Classe `RazorTemplateEngine` removida do core (substituída por `RazorViewTemplateEngine` no pacote `Codout.Mailer.Razor`). - Classe `RazorLightOptions` removida do core. ### Migration Guide diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fe4ddb1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# Instruções para Claude e outros agentes de IA + +## Encoding + +**Todo arquivo criado ou editado neste repositório deve ser salvo em UTF-8 +(sem BOM, salvo quando o tipo de arquivo o exigir).** Não introduza nem +preserve conteúdo em Windows-1252, ISO-8859-1 ou qualquer outra codificação +de byte único. Se encontrar um arquivo legado em outra codificação, converta +para UTF-8 antes de editar. + +Convenção do repositório (também declarada em `.editorconfig`): +- `charset = utf-8` +- `end_of_line = lf` (CRLF apenas em `*.cmd` / `*.bat`) +- `insert_final_newline = true` + +## Versionamento + +- **Cada `.csproj` publicável tem seu próprio ``.** A versão NÃO é mais centralizada em `Directory.Build.props` — não reintroduza-a lá. +- O mapeamento `short-name → caminho.csproj` está em `.github/release-packages.json`. Sempre consulte esse arquivo para resolver o nome curto de um pacote. +- Versionamento segue [SemVer](https://semver.org). Em caso de ambiguidade sobre o nível de bump, **pergunte ao usuário** (patch / minor / major) usando `AskUserQuestion`. + +## Como gerar uma nova versão e publicar um pacote + +Quando o usuário pedir "gerar nova versão e publicar do pacote X" (ou equivalente), siga exatamente esta sequência. Se o usuário pedir apenas "bumpar" / "preparar release" sem mencionar "publicar", **pare antes do passo 6** (não criar tag). + +1. **Resolva pacote + bump level**. Se o usuário não foi explícito: + - Use `.github/release-packages.json` para listar os nomes curtos válidos. + - Use `AskUserQuestion` para confirmar o pacote e/ou o nível de bump quando não estiver óbvio pela natureza das mudanças. +2. **Bump no `.csproj` do pacote alvo.** Edite apenas o `` daquele projeto. NÃO toque em outros `.csproj` nem em `Directory.Build.props`. +3. **Atualize `CHANGELOG.md`** seguindo o formato per-pacote já estabelecido: + ```markdown + ## YYYY-MM-DD + + ### Codout.Framework.X 6.A.B + + #### Fixed | Added | Changed | Removed + - Descrição em português, frase começando com letra maiúscula. + ``` + Se já existe uma seção sob a data de hoje, complemente em vez de duplicar o cabeçalho. Para mudanças cross-cutting (workflow, build, encoding, etc.) use `### Build` ou `### Repository` sob a mesma data. +4. **Commit** no padrão Conventional Commits, com o tipo refletindo a mudança (`fix`, `feat`, `chore`, `docs`, `ci`, `refactor`) e escopo opcional usando o short-name (`fix(ef): ...`, `chore(mailer-razor): ...`). Mensagem em modo imperativo, primeira linha ≤ 72 chars, footer `https://claude.ai/code/session_`. +5. **Push do commit** para o branch de trabalho (geralmente `claude/*` ou direto em `master` se o usuário autorizar). Confirme que o commit está em `origin/master` antes do passo seguinte: + ```bash + git fetch origin master --quiet + git merge-base --is-ancestor HEAD origin/master && echo "on master" || echo "NOT on master" + ``` + Se não estiver em master, **pare e avise o usuário** — o workflow `release.yml` rejeita tags fora de master. +6. **Crie e push da tag** no formato `-v`: + ```bash + git tag -v + git push origin -v + ``` + Isso dispara `.github/workflows/release.yml`, que builda, roda `dotnet test` na solution e publica no NuGet.org via `secrets.NUGET_API_KEY`. **Pushar a tag é a ação que realmente publica.** Só faça nesse passo se a intenção do usuário foi "publicar". Caso contrário, pare no passo 5 e relate o estado. +7. **Relate ao usuário** os SHAs do commit, o nome da tag, e link para a run do workflow no GitHub Actions assim que disponível. + +## Casos especiais + +- **Codout.Framework.Mcp**: usa workflow próprio (`.github/workflows/mcp-release.yml`) com passo `--validate` específico do CLI. Tag deve ser `mcp-v` (NÃO use `mcp` como short-name no `release.yml` — está intencionalmente bloqueado por padrão de tag para evitar duplo release). +- **Mass release** (todos os pacotes de uma vez via `.github/workflows/mass-release.yml`): só execute se o usuário pedir explicitamente "mass release" ou "publicar todos". Mesmo assim, oriente o usuário a disparar via Actions UI com `dry_run: true` primeiro e revisar os artifacts antes de re-disparar com `dry_run: false`. Não tente disparar pela CLI sem autorização explícita. + +## O que NÃO fazer + +- ❌ Reintroduzir `` em `Directory.Build.props`. +- ❌ Bumpar pacotes que não foram tocados pela mudança — cada pacote anda no próprio ritmo. +- ❌ Criar / pushar tag sem o usuário ter pedido "publicar" (a tag é a ação visível externamente que publica no NuGet.org). +- ❌ Disparar `mass-release.yml` sem o usuário pedir explicitamente, nem mesmo via `gh workflow run`. +- ❌ Adivinhar nível de bump em mudanças ambíguas — pergunte. +- ❌ Skippar a verificação de master-ancestry antes de criar a tag. diff --git a/Codout.DynamicLinq/Codout.DynamicLinq.csproj b/Codout.DynamicLinq/Codout.DynamicLinq.csproj index 2d78149..57d3a68 100644 --- a/Codout.DynamicLinq/Codout.DynamicLinq.csproj +++ b/Codout.DynamicLinq/Codout.DynamicLinq.csproj @@ -1,6 +1,7 @@  + 6.2.2 Wrapper para datasource de lista paginada Codout;Framework;DynamicLinq diff --git a/Codout.Framework.Api.Client/Codout.Framework.Api.Client.csproj b/Codout.Framework.Api.Client/Codout.Framework.Api.Client.csproj index 1cdb4e9..1af0ccc 100644 --- a/Codout.Framework.Api.Client/Codout.Framework.Api.Client.csproj +++ b/Codout.Framework.Api.Client/Codout.Framework.Api.Client.csproj @@ -1,6 +1,7 @@  + 6.2.2 Biblioteca de funções para Cliente Api do Framework da Codout diff --git a/Codout.Framework.Api.Dto/Codout.Framework.Api.Dto.csproj b/Codout.Framework.Api.Dto/Codout.Framework.Api.Dto.csproj index 5e6a0a5..4126fb8 100644 --- a/Codout.Framework.Api.Dto/Codout.Framework.Api.Dto.csproj +++ b/Codout.Framework.Api.Dto/Codout.Framework.Api.Dto.csproj @@ -1,6 +1,7 @@  + 6.2.2 netstandard2.1 diff --git a/Codout.Framework.Api/Codout.Framework.Api.csproj b/Codout.Framework.Api/Codout.Framework.Api.csproj index 6cbc43a..533c249 100644 --- a/Codout.Framework.Api/Codout.Framework.Api.csproj +++ b/Codout.Framework.Api/Codout.Framework.Api.csproj @@ -1,6 +1,7 @@  + 6.2.2 Bliblioteca abstrata de implementação para Web API Restfull Codout diff --git a/Codout.Framework.Application/Codout.Framework.Application.csproj b/Codout.Framework.Application/Codout.Framework.Application.csproj index cf86130..c5a5504 100644 --- a/Codout.Framework.Application/Codout.Framework.Application.csproj +++ b/Codout.Framework.Application/Codout.Framework.Application.csproj @@ -1,6 +1,7 @@ + 6.2.2 Bliblioteca de implementação base da camada Application Service Codout diff --git a/Codout.Framework.Common/Codout.Framework.Common.csproj b/Codout.Framework.Common/Codout.Framework.Common.csproj index 6f977a8..36d271d 100644 --- a/Codout.Framework.Common/Codout.Framework.Common.csproj +++ b/Codout.Framework.Common/Codout.Framework.Common.csproj @@ -1,6 +1,7 @@  + 6.2.2 Biblioteca de funcões comuns do Framework da Codout Codout;Framework diff --git a/Codout.Framework.DP/Codout.Framework.DP.csproj b/Codout.Framework.DP/Codout.Framework.DP.csproj index fa19403..75f9079 100644 --- a/Codout.Framework.DP/Codout.Framework.DP.csproj +++ b/Codout.Framework.DP/Codout.Framework.DP.csproj @@ -1,6 +1,7 @@ + 6.2.2 netstandard2.1 diff --git a/Codout.Framework.Data/Codout.Framework.Data.csproj b/Codout.Framework.Data/Codout.Framework.Data.csproj index c25c3d0..4f1e668 100644 --- a/Codout.Framework.Data/Codout.Framework.Data.csproj +++ b/Codout.Framework.Data/Codout.Framework.Data.csproj @@ -1,6 +1,7 @@  + 6.2.2 Interface da Biblioteca de persistência do Framework da Codout Codout;Framework;ORM;DAL;Repository;UnitOfWork;Specification;Auditing true diff --git a/Codout.Framework.Data/IMPLEMENTATION_UPDATE_GUIDE.md b/Codout.Framework.Data/IMPLEMENTATION_UPDATE_GUIDE.md index 7ec8b27..dd543ed 100644 --- a/Codout.Framework.Data/IMPLEMENTATION_UPDATE_GUIDE.md +++ b/Codout.Framework.Data/IMPLEMENTATION_UPDATE_GUIDE.md @@ -1,14 +1,14 @@ -# Guia de Atualiza��o para Implementa��es +# Guia de Atualização para Implementações ## ?? Objetivo -Este guia ajuda mantenedores de implementa��es (`Codout.Framework.NH`, `Codout.Framework.Mongo`) a atualizar seus projetos para as novas interfaces do `Codout.Framework.Data` v10.0. +Este guia ajuda mantenedores de implementações (`Codout.Framework.NH`, `Codout.Framework.Mongo`) a atualizar seus projetos para as novas interfaces do `Codout.Framework.Data` v10.0. -## ?? Mudan�as Necess�rias +## ?? Mudanças Necessárias ### IRepository\ - Novas Sobrecargas -Todos os m�todos async agora possuem sobrecargas com `CancellationToken`: +Todos os métodos async agora possuem sobrecargas com `CancellationToken`: ```csharp // ? Adicionar estas sobrecarg @@ -25,17 +25,17 @@ Task MergeAsync(T entity, CancellationToken cancellationToken); Task RefreshAsync(T entity, CancellationToken cancellationToken); ``` -### IRepository\ - Novos M�todos Auxiliares +### IRepository\ - Novos Métodos Auxiliares ```csharp -// ? Implementar estes novos m�todos +// ? Implementar estes novos métodos Task FirstOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default); Task AnyAsync(Expression> predicate, CancellationToken cancellationToken = default); Task CountAsync(Expression> predicate, CancellationToken cancellationToken = default); Task> ToListAsync(Expression> predicate, CancellationToken cancellationToken = default); ``` -### IUnitOfWork - M�todos Async +### IUnitOfWork - Métodos Async ```csharp // ? Implementar suporte async completo @@ -78,7 +78,7 @@ public class NHRepository : IRepository where T : class, IEntity ```csharp public class NHRepository : IRepository where T : class, IEntity { - // Manter m�todo original para retrocompatibilidade + // Manter método original para retrocompatibilidade public async Task GetAsync(Expression> predicate) { return await GetAsync(predicate, CancellationToken.None); @@ -90,7 +90,7 @@ public class NHRepository : IRepository where T : class, IEntity return await Session.Query().SingleOrDefaultAsync(predicate, cancellationToken); } - // Novos m�todos auxiliares + // Novos métodos auxiliares public async Task FirstOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default) { return await Session.Query().FirstOrDefaultAsync(predicate, cancellationToken); @@ -132,7 +132,7 @@ public class MongoRepository : IRepository where T : class, IEntity ```csharp public class MongoRepository : IRepository where T : class, IEntity { - // Manter m�todo original + // Manter método original public async Task GetAsync(Expression> predicate) { return await GetAsync(predicate, CancellationToken.None); @@ -144,7 +144,7 @@ public class MongoRepository : IRepository where T : class, IEntity return await Collection.Find(predicate).SingleOrDefaultAsync(cancellationToken); } - // Novos m�todos auxiliares + // Novos métodos auxiliares public async Task FirstOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default) { return await Collection.Find(predicate).FirstOrDefaultAsync(cancellationToken); @@ -167,16 +167,16 @@ public class MongoRepository : IRepository where T : class, IEntity } ``` -## ?? Checklist de Atualiza��o +## ?? Checklist de Atualização ### IRepository\ -- [ ] Adicionar sobrecargas com `CancellationToken` em todos m�todos async existentes +- [ ] Adicionar sobrecargas com `CancellationToken` em todos métodos async existentes - [ ] Implementar `FirstOrDefaultAsync` - [ ] Implementar `AnyAsync` - [ ] Implementar `CountAsync` - [ ] Implementar `ToListAsync` -- [ ] Redirecionar m�todos antigos para novos (passando `CancellationToken.None`) +- [ ] Redirecionar métodos antigos para novos (passando `CancellationToken.None`) ### IUnitOfWork @@ -189,35 +189,35 @@ public class MongoRepository : IRepository where T : class, IEntity ### Testes -- [ ] Testar todos os novos m�todos +- [ ] Testar todos os novos métodos - [ ] Testar cancelamento com `CancellationToken` -- [ ] Testar transa��es async +- [ ] Testar transações async - [ ] Verificar retrocompatibilidade -## ?? Refer�ncia: Entity Framework Core +## ?? Referência: Entity Framework Core -O `Codout.Framework.EF` j� est� completamente atualizado. Use-o como refer�ncia: +O `Codout.Framework.EF` já está completamente atualizado. Use-o como referência: - **Arquivo**: `Codout.Framework.EF\EFRepository.cs` - **Arquivo**: `Codout.Framework.EF\EFUnitOfWork.cs` ## ?? Dicas -1. **N�o quebre retrocompatibilidade**: Mantenha os m�todos antigos chamando os novos -2. **Use `CancellationToken.None`**: Como padr�o para m�todos sem par�metro +1. **Não quebre retrocompatibilidade**: Mantenha os métodos antigos chamando os novos +2. **Use `CancellationToken.None`**: Como padrão para métodos sem parâmetro 3. **Teste cancelamento**: Verifique se `CancellationToken` realmente cancela -4. **Documente**: Adicione XML comments nos novos m�todos +4. **Documente**: Adicione XML comments nos novos métodos ## ?? Suporte Se encontrar dificuldades: -1. Consulte a implementa��o do `Codout.Framework.EF` -2. Revise a documenta��o no `Codout.Framework.Data\README.md` +1. Consulte a implementação do `Codout.Framework.EF` +2. Revise a documentação no `Codout.Framework.Data\README.md` 3. Contate a equipe de arquitetura --- -**Vers�o**: 10.0.0 -**Status**: Aguardando atualiza��o de NH e Mongo +**Versão**: 10.0.0 +**Status**: Aguardando atualização de NH e Mongo **Prioridade**: Alta diff --git a/Codout.Framework.Data/README.md b/Codout.Framework.Data/README.md index 67e34bd..865422a 100644 --- a/Codout.Framework.Data/README.md +++ b/Codout.Framework.Data/README.md @@ -1,17 +1,17 @@ # Codout.Framework.Data -**Abstra��es de persist�ncia ORM-agnostic para .NET 10** +**Abstrações de persistência ORM-agnostic para .NET 10** -Este projeto define os contratos (interfaces) para implementa��o de padr�es Repository e Unit of Work, independente de tecnologia de persist�ncia. +Este projeto define os contratos (interfaces) para implementação de padrões Repository e Unit of Work, independente de tecnologia de persistência. ## ?? Objetivo -Fornecer abstra��es que podem ser implementadas por qualquer ORM: +Fornecer abstrações que podem ser implementadas por qualquer ORM: - ? Entity Framework Core ([`Codout.Framework.EF`](../Codout.Framework.EF/README.md)) - ? NHibernate ([`Codout.Framework.NH`](../Codout.Framework.NH/README.md)) - ? MongoDB ([`Codout.Framework.Mongo`](../Codout.Framework.Mongo/README.md)) -## ?? Instala��o +## ?? Instalação ```bash dotnet add package Codout.Framework.Data @@ -22,7 +22,7 @@ dotnet add package Codout.Framework.Data ### Contratos Principais #### IEntity / IEntity\ -Define a base para todas as entidades do dom�nio. +Define a base para todas as entidades do domínio. ```csharp public interface IEntity @@ -38,7 +38,7 @@ public interface IEntity : IEntity ``` #### IRepository\ -Define opera��es CRUD gen�ricas para entidades. +Define operações CRUD genéricas para entidades. ```csharp public interface IRepository : IDisposable where T : class, IEntity @@ -72,7 +72,7 @@ public interface IRepository : IDisposable where T : class, IEntity ``` #### IUnitOfWork -Define o padr�o Unit of Work para gerenciamento de transa��es. +Define o padrão Unit of Work para gerenciamento de transações. ```csharp public interface IUnitOfWork : IDisposable, IAsyncDisposable @@ -99,7 +99,7 @@ public interface IUnitOfWork : IDisposable, IAsyncDisposable ### Specification Pattern (v10.0+) #### ISpecification\ -Define especifica��es reutiliz�veis para consultas complexas. +Define especificações reutilizáveis para consultas complexas. ```csharp public interface ISpecification where T : class, IEntity @@ -132,7 +132,7 @@ public class ActiveProductsSpec : Specification ### Auditing Interfaces (v10.0+) #### IAuditable -Para entidades que precisam de auditoria autom�tica. +Para entidades que precisam de auditoria automática. ```csharp public interface IAuditable @@ -145,7 +145,7 @@ public interface IAuditable ``` #### ISoftDeletable -Para entidades com soft delete (exclus�o l�gica). +Para entidades com soft delete (exclusão lógica). ```csharp public interface ISoftDeletable @@ -157,7 +157,7 @@ public interface ISoftDeletable ``` #### ICurrentUserProvider -Provider para obter o usu�rio atual. +Provider para obter o usuário atual. ```csharp public interface ICurrentUserProvider @@ -166,7 +166,7 @@ public interface ICurrentUserProvider } ``` -**Exemplo de Implementa��o:** +**Exemplo de Implementação:** ```csharp public class HttpContextUserProvider : ICurrentUserProvider { @@ -184,7 +184,7 @@ public class HttpContextUserProvider : ICurrentUserProvider } ``` -## ?? Implementando as Abstra��es +## ?? Implementando as Abstrações ### Exemplo: Entity Framework Core @@ -207,7 +207,7 @@ public class EFRepository : IRepository where T : class, IEntity public async Task AnyAsync(Expression> predicate, CancellationToken ct = default) => await DbSet.AnyAsync(predicate, ct); - // ... implementar outros m�todos + // ... implementar outros métodos } ``` @@ -235,7 +235,7 @@ public class EFUnitOfWork : IUnitOfWork await _transaction?.CommitAsync(ct); } - // ... implementar outros m�todos + // ... implementar outros métodos } ``` @@ -312,15 +312,15 @@ public class ProductService ## ?? Novidades v10.0 ### Breaking Changes -**Nenhum!** Todas as mudan�as s�o aditivas e retrocompat�veis. +**Nenhum!** Todas as mudanças são aditivas e retrocompatíveis. ### Novas Interfaces - ? `ISpecification` - Specification Pattern -- ? `IAuditable` - Auditoria autom�tica +- ? `IAuditable` - Auditoria automática - ? `ISoftDeletable` - Soft delete -- ? `ICurrentUserProvider` - Provider de usu�rio +- ? `ICurrentUserProvider` - Provider de usuário -### M�todos Adicionados +### Métodos Adicionados #### IUnitOfWork - ? `Task BeginTransactionAsync(CancellationToken)` @@ -331,7 +331,7 @@ public class ProductService - ? `IAsyncDisposable` support #### IRepository\ -- ? Sobrecargas com `CancellationToken` em todos m�todos async +- ? Sobrecargas com `CancellationToken` em todos métodos async - ? `Task FirstOrDefaultAsync(Expression, CancellationToken)` - ? `Task AnyAsync(Expression, CancellationToken)` - ? `Task CountAsync(Expression, CancellationToken)` @@ -342,15 +342,15 @@ public class ProductService ## ?? Compatibilidade -| Implementa��o | Status | Vers�o | Link | +| Implementação | Status | Versão | Link | |---------------|--------|--------|------| | **Entity Framework Core** | ? Completo | 10.0.0 | [README](../Codout.Framework.EF/README.md) | | **NHibernate** | ? Completo | 10.0.0 | [README](../Codout.Framework.NH/README.md) | | **MongoDB** | ? Completo | 10.0.0 | [README](../Codout.Framework.Mongo/README.md) | -## ?? Pr�ximos Passos +## ?? Próximos Passos -1. Escolha uma implementa��o: +1. Escolha uma implementação: - [Codout.Framework.EF](../Codout.Framework.EF/README.md) - Entity Framework Core - [Codout.Framework.NH](../Codout.Framework.NH/README.md) - NHibernate - [Codout.Framework.Mongo](../Codout.Framework.Mongo/README.md) - MongoDB @@ -359,25 +359,25 @@ public class ProductService 3. Adicione auditoria com `IAuditable` e soft delete com `ISoftDeletable` -4. Use `ISpecification` para queries complexas reutiliz�veis +4. Use `ISpecification` para queries complexas reutilizáveis -5. Gerencie transa��es com `IUnitOfWork` +5. Gerencie transações com `IUnitOfWork` ## ?? Qualidade -- ? **100% retrocompat�vel** com vers�es anteriores +- ? **100% retrocompatível** com versões anteriores - ? **Nullable Reference Types** habilitado -- ? **Documenta��o XML** completa -- ? **CancellationToken** em todas opera��es async +- ? **Documentação XML** completa +- ? **CancellationToken** em todas operações async - ? **IAsyncDisposable** suportado - ? **Specification Pattern** para queries complexas - ? **Auditing** e **Soft Delete** built-in -## ?? Compara��o de Implementa��es +## ?? Comparação de Implementações | Recurso | EF Core | NHibernate | MongoDB | |---------|---------|------------|---------| -| Transa��es | ? | ? | ? (replica set) | +| Transações | ? | ? | ? (replica set) | | Lazy Loading | ? | ? (virtual) | ? | | Change Tracking | ? | ? | ? | | LINQ Support | ??? | ?? | ? | @@ -386,12 +386,12 @@ public class ProductService | Interceptors | ? | ?? | ? | | Specifications | ? | ? | ? | -## ?? Licen�a +## ?? Licença Propriedade da Codout --- -**Vers�o:** 10.0.0 -**Status:** Est�vel para produ��o +**Versão:** 10.0.0 +**Status:** Estável para produção **Target:** .NET 10 diff --git a/Codout.Framework.Domain/Codout.Framework.Domain.csproj b/Codout.Framework.Domain/Codout.Framework.Domain.csproj index b2dc731..714164e 100644 --- a/Codout.Framework.Domain/Codout.Framework.Domain.csproj +++ b/Codout.Framework.Domain/Codout.Framework.Domain.csproj @@ -1,6 +1,7 @@  + 6.2.2 Camada de Domínio do Framework da Codout Codout;Framework;Domain; diff --git a/Codout.Framework.EF/Codout.Framework.EF.csproj b/Codout.Framework.EF/Codout.Framework.EF.csproj index eeecf15..50abc24 100644 --- a/Codout.Framework.EF/Codout.Framework.EF.csproj +++ b/Codout.Framework.EF/Codout.Framework.EF.csproj @@ -1,6 +1,7 @@  + 6.3.0 Implementação da interface Codout.Framework.DAL para EntityFrameworkCore Codout;Framework;ORM;DAL;EntityFrameworkCore;Repository;UnitOfWork;Specification true diff --git a/Codout.Framework.EF/EFCoreBuilder.cs b/Codout.Framework.EF/EFCoreBuilder.cs index 877ec31..86f9b8c 100644 --- a/Codout.Framework.EF/EFCoreBuilder.cs +++ b/Codout.Framework.EF/EFCoreBuilder.cs @@ -9,7 +9,7 @@ namespace Codout.Framework.EF; /// -/// Builder fluente para configura��o avan�ada do Entity Framework Core +/// Builder fluente para configuração avançada do Entity Framework Core /// public class EFCoreBuilder where TContext : DbContext { @@ -41,13 +41,13 @@ public EFCoreBuilder WithConnectionString(string connectionString) } /// - /// Carrega a connection string da configura��o + /// Carrega a connection string da configuração /// public EFCoreBuilder WithConnectionStringFromConfiguration(string key = "DefaultConnection") { _connectionString = _configuration.GetConnectionString(key); if (string.IsNullOrEmpty(_connectionString)) - throw new InvalidOperationException($"Connection string '{key}' n�o encontrada na configura��o."); + throw new InvalidOperationException($"Connection string '{key}' não encontrada na configuração."); return this; } @@ -59,7 +59,7 @@ public EFCoreBuilder UseSqlServer(Action { if (string.IsNullOrEmpty(_connectionString)) - throw new InvalidOperationException("Connection string n�o configurada. Use WithConnectionString() primeiro."); + throw new InvalidOperationException("Connection string não configurada. Use WithConnectionString() primeiro."); options.UseSqlServer(_connectionString, sqlOptions => { @@ -87,7 +87,7 @@ public EFCoreBuilder AddInterceptor() where TInterceptor } /// - /// Habilita auditoria autom�tica + /// Habilita auditoria automática /// public EFCoreBuilder EnableAuditing() { @@ -96,7 +96,7 @@ public EFCoreBuilder EnableAuditing() } /// - /// Habilita soft delete autom�tico + /// Habilita soft delete automático /// public EFCoreBuilder EnableSoftDelete() { @@ -105,7 +105,7 @@ public EFCoreBuilder EnableSoftDelete() } /// - /// Habilita logging de dados sens�veis (apenas desenvolvimento) + /// Habilita logging de dados sensíveis (apenas desenvolvimento) /// public EFCoreBuilder EnableSensitiveDataLogging() { @@ -123,7 +123,7 @@ public EFCoreBuilder EnableDetailedErrors() } /// - /// Habilita retry autom�tico em falhas + /// Habilita retry automático em falhas /// public EFCoreBuilder EnableRetryOnFailure(int maxRetryCount = 3, int maxRetryDelaySeconds = 30) { @@ -143,7 +143,7 @@ public EFCoreBuilder WithLifetime(ServiceLifetime lifetime) } /// - /// Configura��o customizada do DbContextOptionsBuilder + /// Configuração customizada do DbContextOptionsBuilder /// public EFCoreBuilder ConfigureOptions(Action configure) { @@ -157,12 +157,12 @@ public EFCoreBuilder ConfigureOptions(Action } /// - /// Finaliza a configura��o e registra o DbContext + /// Finaliza a configuração e registra o DbContext /// public IServiceCollection Build() { if (_configureOptions == null) - throw new InvalidOperationException("Provider n�o configurado. Use UseSqlServer() ou outro provider."); + throw new InvalidOperationException("Provider não configurado. Use UseSqlServer() ou outro provider."); _services.AddDbContext((serviceProvider, options) => { @@ -190,12 +190,12 @@ public IServiceCollection Build() } /// -/// Extens�es do ServiceCollection para o builder +/// Extensões do ServiceCollection para o builder /// public static class EFCoreBuilderExtensions { /// - /// Adiciona Entity Framework Core com configura��o fluente + /// Adiciona Entity Framework Core com configuração fluente /// public static EFCoreBuilder AddEFCore( this IServiceCollection services, diff --git a/Codout.Framework.EF/EFRepository.cs b/Codout.Framework.EF/EFRepository.cs index 197f00a..f1afe20 100644 --- a/Codout.Framework.EF/EFRepository.cs +++ b/Codout.Framework.EF/EFRepository.cs @@ -64,13 +64,79 @@ public T Save(T entity) public T SaveOrUpdate(T entity) { ArgumentNullException.ThrowIfNull(entity); - if (entity.IsTransient()) - DbSet.Add(entity); - else - Update(entity); + + if (TryResolveTrackedOrAdd(entity, out var keyValues)) + return entity; + + var existing = DbSet.Find(keyValues); + ApplySaveOrUpdate(entity, existing); return entity; } + // Returns true if no DB lookup is needed (already tracked, no PK metadata, or key unset → Add). + // When false, keyValues contains the primary-key values to look up. + private bool TryResolveTrackedOrAdd(T entity, out object[] keyValues) + { + keyValues = null; + + var entry = Context.Entry(entity); + + // Already tracked - EF knows what to do on SaveChanges. + if (entry.State != EntityState.Detached) + return true; + + // For detached entities, decide insert vs. update by inspecting the primary key + // rather than IEntity.IsTransient(), which is unreliable when callers pre-assign + // the Id (e.g. Guid.NewGuid() in the constructor). + var primaryKey = Context.Model.FindEntityType(typeof(T))?.FindPrimaryKey(); + if (primaryKey == null) + { + DbSet.Add(entity); + return true; + } + + keyValues = primaryKey.Properties + .Select(p => entry.Property(p.Name).CurrentValue) + .ToArray(); + + if (keyValues.Any(IsUnsetKeyValue)) + { + DbSet.Add(entity); + return true; + } + + return false; + } + + private void ApplySaveOrUpdate(T entity, T existing) + { + if (existing == null) + { + // Non-transient Id but row doesn't exist yet - new entity with a pre-assigned key + // (the case IsTransient() gets wrong). + DbSet.Add(entity); + return; + } + + if (ReferenceEquals(existing, entity)) + { + Context.Entry(entity).State = EntityState.Modified; + return; + } + + // Find() attached `existing` with OriginalValues from the database. Copying the + // incoming values into it preserves concurrency tokens (e.g. [Timestamp]) and lets + // EF generate the correct WHERE clause on UPDATE. + Context.Entry(existing).CurrentValues.SetValues(entity); + } + + private static bool IsUnsetKeyValue(object value) + { + if (value is null) return true; + var type = value.GetType(); + return type.IsValueType && value.Equals(Activator.CreateInstance(type)); + } + public void Update(T entity) { ArgumentNullException.ThrowIfNull(entity); @@ -156,16 +222,19 @@ public Task SaveAsync(T entity, CancellationToken cancellationToken) return Task.FromResult(entity); } - public Task SaveOrUpdateAsync(T entity) - { - SaveOrUpdate(entity); - return Task.FromResult(entity); - } + public Task SaveOrUpdateAsync(T entity) => + SaveOrUpdateAsync(entity, CancellationToken.None); - public Task SaveOrUpdateAsync(T entity, CancellationToken cancellationToken) + public async Task SaveOrUpdateAsync(T entity, CancellationToken cancellationToken) { - SaveOrUpdate(entity); - return Task.FromResult(entity); + ArgumentNullException.ThrowIfNull(entity); + + if (TryResolveTrackedOrAdd(entity, out var keyValues)) + return entity; + + var existing = await DbSet.FindAsync(keyValues, cancellationToken); + ApplySaveOrUpdate(entity, existing); + return entity; } public Task UpdateAsync(T entity) diff --git a/Codout.Framework.EF/Interceptors/AuditableInterceptor.cs b/Codout.Framework.EF/Interceptors/AuditableInterceptor.cs index 258c3c4..9fdac41 100644 --- a/Codout.Framework.EF/Interceptors/AuditableInterceptor.cs +++ b/Codout.Framework.EF/Interceptors/AuditableInterceptor.cs @@ -10,7 +10,7 @@ namespace Codout.Framework.EF.Interceptors; /// -/// Interceptor para auditoria autom�tica de entidades que implementam IAuditable +/// Interceptor para auditoria automática de entidades que implementam IAuditable /// public class AuditableInterceptor : SaveChangesInterceptor { @@ -68,7 +68,7 @@ private void UpdateAuditableEntities(DbContext? context) } /// -/// Interface para entidades audit�veis +/// Interface para entidades auditáveis /// public interface IAuditable { @@ -79,7 +79,7 @@ public interface IAuditable } /// -/// Provider para obter o usu�rio atual (implementar conforme seu sistema de autentica��o) +/// Provider para obter o usuário atual (implementar conforme seu sistema de autenticação) /// public interface ICurrentUserProvider { diff --git a/Codout.Framework.EF/Interceptors/SoftDeleteInterceptor.cs b/Codout.Framework.EF/Interceptors/SoftDeleteInterceptor.cs index d0a327b..e2de648 100644 --- a/Codout.Framework.EF/Interceptors/SoftDeleteInterceptor.cs +++ b/Codout.Framework.EF/Interceptors/SoftDeleteInterceptor.cs @@ -10,7 +10,7 @@ namespace Codout.Framework.EF.Interceptors; /// -/// Interceptor para soft delete autom�tico de entidades que implementam ISoftDeletable +/// Interceptor para soft delete automático de entidades que implementam ISoftDeletable /// public class SoftDeleteInterceptor : SaveChangesInterceptor { diff --git a/Codout.Framework.EF/MIGRATION_GUIDE.md b/Codout.Framework.EF/MIGRATION_GUIDE.md index a6f080b..50ad651 100644 --- a/Codout.Framework.EF/MIGRATION_GUIDE.md +++ b/Codout.Framework.EF/MIGRATION_GUIDE.md @@ -1,32 +1,32 @@ -# Guia de Migra��o - Codout.Framework.EF v10.0 +# Guia de Migração - Codout.Framework.EF v10.0 ## ?? Objetivo -Este guia ajudar� voc� a migrar c�digo existente para a nova vers�o v10.0 do Codout.Framework.EF com melhorias enterprise. +Este guia ajudará você a migrar código existente para a nova versão v10.0 do Codout.Framework.EF com melhorias enterprise. -## ?? Sum�rio de Mudan�as +## ?? Sumário de Mudanças ### ? Compatibilidade Mantida -- ? Interface `IRepository` n�o foi alterada -- ? Interface `IUnitOfWork` n�o foi alterada (apenas adicionados m�todos async) -- ? `EFRepository` mant�m todas as funcionalidades anteriores -- ? `EFUnitOfWork` mant�m API existente - -### ? Melhorias Cr�ticas -- ?? **Bug cr�tico corrigido**: Transa��es no UnitOfWork agora funcionam corretamente -- ?? **Memory leak resolvido**: Repository n�o faz mais dispose do DbContext +- ? Interface `IRepository` não foi alterada +- ? Interface `IUnitOfWork` não foi alterada (apenas adicionados métodos async) +- ? `EFRepository` mantém todas as funcionalidades anteriores +- ? `EFUnitOfWork` mantém API existente + +### ? Melhorias Críticas +- ?? **Bug crítico corrigido**: Transações no UnitOfWork agora funcionam corretamente +- ?? **Memory leak resolvido**: Repository não faz mais dispose do DbContext - ? **Performance**: Melhorias em queries read-only ### ?? Novos Recursos - ? Specification Pattern - ? Interceptors (Auditoria e Soft Delete) -- ? Builder fluente para configura��o -- ? M�todos async adicionais no UnitOfWork -- ? Extens�es com CancellationToken +- ? Builder fluente para configuração +- ? Métodos async adicionais no UnitOfWork +- ? Extensões com CancellationToken -## ?? Mudan�as Necess�rias +## ?? Mudanças Necessárias -### 1. Configura��o do DbContext +### 1. Configuração do DbContext #### ? Antes (ainda funciona, mas deprecated) @@ -43,30 +43,30 @@ services.AddEFCore(configuration) .Build(); ``` -**Motivo**: Maior flexibilidade e suporte a configura��es avan�adas. +**Motivo**: Maior flexibilidade e suporte a configurações avançadas. -**A��o**: Atualizar na primeira oportunidade. O m�todo antigo continuar� funcionando mas mostrar� warning. +**Ação**: Atualizar na primeira oportunidade. O método antigo continuará funcionando mas mostrará warning. --- -### 2. Unit of Work - Transa��es +### 2. Unit of Work - Transações -#### ? Antes (bug cr�tico) +#### ? Antes (bug crítico) ```csharp -// Commit() criava transa��o automaticamente se n�o existisse -// e engolia exce��es silenciosamente +// Commit() criava transação automaticamente se não existisse +// e engolia exceções silenciosamente uow.Commit(); // ?? COMPORTAMENTO INCORRETO ``` #### ? Depois (correto) ```csharp -// Agora voc� DEVE criar a transa��o explicitamente +// Agora você DEVE criar a transação explicitamente await uow.BeginTransactionAsync(); try { - // opera��es... + // operações... await uow.CommitAsync(); } catch @@ -76,9 +76,9 @@ catch } ``` -**Motivo**: Prevenir commits acidentais e melhorar controle de transa��es. +**Motivo**: Prevenir commits acidentais e melhorar controle de transações. -**A��o**: **CR�TICO** - Revisar TODO c�digo que usa `Commit()` sem `BeginTransaction()` expl�cito. +**Ação**: **CRÍTICO** - Revisar TODO código que usa `Commit()` sem `BeginTransaction()` explícito. --- @@ -89,7 +89,7 @@ catch ```csharp var result = uow.InTransaction(() => { - // opera��o s�ncrona + // operação síncrona return entity; }); ``` @@ -99,14 +99,14 @@ var result = uow.InTransaction(() => ```csharp var result = await uow.InTransactionAsync(async () => { - // opera��o ass�ncrona + // operação assíncrona return entity; }); ``` **Motivo**: Suporte completo a async/await. -**A��o**: Considerar migrar para vers�o async para melhor performance. +**Ação**: Considerar migrar para versão async para melhor performance. --- @@ -119,18 +119,18 @@ var products = await repository.GetAsync(p => p.IsActive); // Sem suporte a cancelamento ``` -#### ? Depois (com extens�es) +#### ? Depois (com extensões) ```csharp -using Codout.Framework.EF; // Para usar extens�es +using Codout.Framework.EF; // Para usar extensões var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); var products = await repository.GetAsync(p => p.IsActive, cts.Token); ``` -**Motivo**: Permitir cancelamento de opera��es longas. +**Motivo**: Permitir cancelamento de operações longas. -**A��o**: Opcional, mas recomendado para APIs web e opera��es longas. +**Ação**: Opcional, mas recomendado para APIs web e operações longas. --- @@ -138,7 +138,7 @@ var products = await repository.GetAsync(p => p.IsActive, cts.Token); ### Specification Pattern -**Quando usar**: Queries complexas reutiliz�veis em m�ltiplos lugares. +**Quando usar**: Queries complexas reutilizáveis em múltiplos lugares. ```csharp // Criar specification @@ -158,11 +158,11 @@ var spec = new ActiveProductsSpec(); var products = await repository.ListAsync(spec); ``` -**Benef�cio**: Queries complexas test�veis e reutiliz�veis. +**Benefício**: Queries complexas testáveis e reutilizáveis. --- -### Auditoria Autom�tica +### Auditoria Automática **Quando usar**: Entidades que precisam rastrear quem criou/modificou. @@ -192,11 +192,11 @@ services.AddEFCore(configuration) services.AddSingleton(); ``` -**Benef�cio**: Auditoria autom�tica sem c�digo manual. +**Benefício**: Auditoria automática sem código manual. --- -### Soft Delete Autom�tico +### Soft Delete Automático **Quando usar**: Nunca deletar dados fisicamente. @@ -229,52 +229,52 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } ``` -**Benef�cio**: Soft delete autom�tico + hist�rico preservado. +**Benefício**: Soft delete automático + histórico preservado. --- -## ?? Checklist de Migra��o +## ?? Checklist de Migração -### Prioridade ALTA (Bugs Cr�ticos) +### Prioridade ALTA (Bugs Críticos) - [ ] **Revisar todas chamadas a `Commit()` sem `BeginTransaction()`** - Arquivo: Buscar por `\.Commit\(\)` em todo projeto - - A��o: Adicionar `BeginTransaction()` antes ou usar `InTransaction()` + - Ação: Adicionar `BeginTransaction()` antes ou usar `InTransaction()` -- [ ] **Verificar dispose de DbContext em reposit�rios customizados** - - Se voc� sobrescreveu `Dispose()`, remova o dispose do DbContext +- [ ] **Verificar dispose de DbContext em repositórios customizados** + - Se você sobrescreveu `Dispose()`, remova o dispose do DbContext -### Prioridade M�DIA (Melhorias) +### Prioridade MÉDIA (Melhorias) -- [ ] Atualizar configura��o do DbContext para usar builder fluente -- [ ] Adicionar suporte a CancellationToken em opera��es cr�ticas -- [ ] Migrar para m�todos async do UnitOfWork (`BeginTransactionAsync`, `CommitAsync`) +- [ ] Atualizar configuração do DbContext para usar builder fluente +- [ ] Adicionar suporte a CancellationToken em operações críticas +- [ ] Migrar para métodos async do UnitOfWork (`BeginTransactionAsync`, `CommitAsync`) ### Prioridade BAIXA (Novos Recursos) - [ ] Avaliar uso de Specification Pattern para queries complexas - [ ] Implementar IAuditable em entidades importantes -- [ ] Implementar ISoftDeletable em vez de delete f�sico -- [ ] Configurar retry policies para resili�ncia +- [ ] Implementar ISoftDeletable em vez de delete físico +- [ ] Configurar retry policies para resiliência - [ ] Adicionar telemetria e health checks --- -## ?? Como Encontrar C�digo Afetado +## ?? Como Encontrar Código Afetado -### 1. Buscar transa��es sem BeginTransaction +### 1. Buscar transações sem BeginTransaction ```regex \.Commit\(\)(?!.*BeginTransaction) ``` -### 2. Buscar uso de InTransaction s�ncrono +### 2. Buscar uso de InTransaction síncrono ```regex \.InTransaction\((?!.*async) ``` -### 3. Buscar reposit�rios com dispose customizado +### 3. Buscar repositórios com dispose customizado ```regex class.*Repository.*\n.*Dispose\( @@ -286,11 +286,11 @@ class.*Repository.*\n.*Dispose\( ### Nenhum Breaking Change Real -A vers�o v10.0 foi projetada para ser **100% retrocompat�vel**. Todos os "breaking changes" s�o na verdade: +A versão v10.0 foi projetada para ser **100% retrocompatível**. Todos os "breaking changes" são na verdade: -1. **Corre��es de bugs** que j� deveriam funcionar assim -2. **Deprecation warnings** para m�todos legados -3. **Melhorias de design** que n�o quebram c�digo existente +1. **Correções de bugs** que já deveriam funcionar assim +2. **Deprecation warnings** para métodos legados +3. **Melhorias de design** que não quebram código existente ### Deprecations (Warnings) @@ -308,35 +308,35 @@ services.AddEFCore(configuration); ## ?? Recursos Adicionais -- [README.md](README.md) - Documenta��o completa -- [Interceptors](Interceptors/) - C�digo dos interceptors -- [Specifications](Specifications/) - C�digo do Specification Pattern +- [README.md](README.md) - Documentação completa +- [Interceptors](Interceptors/) - Código dos interceptors +- [Specifications](Specifications/) - Código do Specification Pattern --- ## ?? Suporte -Se encontrar problemas durante a migra��o: +Se encontrar problemas durante a migração: 1. Verifique se seguiu todos os passos do checklist -2. Revise a documenta��o no README.md +2. Revise a documentação no README.md 3. Consulte a equipe de arquitetura da Codout --- ## ?? Impacto Estimado -| Projeto | Esfor�o de Migra��o | Risco | +| Projeto | Esforço de Migração | Risco | |---------|-------------------|-------| | Pequeno (<10 entidades) | 1-2 horas | Baixo | -| M�dio (10-50 entidades) | 4-8 horas | M�dio | -| Grande (>50 entidades) | 2-3 dias | M�dio | +| Médio (10-50 entidades) | 4-8 horas | Médio | +| Grande (>50 entidades) | 2-3 dias | Médio | -**Nota**: O maior esfor�o � na revis�o de transa��es. O resto � opcional. +**Nota**: O maior esforço é na revisão de transações. O resto é opcional. --- -## ? Exemplo Completo de Migra��o +## ? Exemplo Completo de Migração ### Antes @@ -348,7 +348,7 @@ services.AddEFCore(configuration); public void CreateProduct(Product product) { repository.Save(product); - uow.Commit(); // ?? Bug: n�o chamou BeginTransaction + uow.Commit(); // ?? Bug: não chamou BeginTransaction } ``` @@ -400,5 +400,5 @@ public async Task CreateProductAsync(Product product, CancellationToken ct = def --- **Data**: Janeiro 2025 -**Vers�o**: v10.0.0 -**Status**: Est�vel para produ��o +**Versão**: v10.0.0 +**Status**: Estável para produção diff --git a/Codout.Framework.EF/RepositorySpecificationExtensions.cs b/Codout.Framework.EF/RepositorySpecificationExtensions.cs index d65a1fb..c1c0594 100644 --- a/Codout.Framework.EF/RepositorySpecificationExtensions.cs +++ b/Codout.Framework.EF/RepositorySpecificationExtensions.cs @@ -9,7 +9,7 @@ namespace Codout.Framework.EF; /// -/// Extens�es do Repository para suportar Specification Pattern +/// Extensões do Repository para suportar Specification Pattern /// public static class RepositorySpecificationExtensions { diff --git a/Codout.Framework.EF/Specifications/Specification.cs b/Codout.Framework.EF/Specifications/Specification.cs index 9219958..eb3920a 100644 --- a/Codout.Framework.EF/Specifications/Specification.cs +++ b/Codout.Framework.EF/Specifications/Specification.cs @@ -9,7 +9,7 @@ namespace Codout.Framework.EF.Specifications; /// -/// Implementa��o base do Specification Pattern para Entity Framework Core +/// Implementação base do Specification Pattern para Entity Framework Core /// public abstract class Specification : ISpecification where T : class, IEntity { diff --git a/Codout.Framework.Mcp/src/Tools/Codout.Framework.Mcp/Codout.Framework.Mcp.csproj b/Codout.Framework.Mcp/src/Tools/Codout.Framework.Mcp/Codout.Framework.Mcp.csproj index af9baba..84dde9f 100644 --- a/Codout.Framework.Mcp/src/Tools/Codout.Framework.Mcp/Codout.Framework.Mcp.csproj +++ b/Codout.Framework.Mcp/src/Tools/Codout.Framework.Mcp/Codout.Framework.Mcp.csproj @@ -1,6 +1,7 @@ + 6.2.2 Exe net10.0 enable diff --git a/Codout.Framework.Mongo/Codout.Framework.Mongo.csproj b/Codout.Framework.Mongo/Codout.Framework.Mongo.csproj index 3a643cb..9d5376c 100644 --- a/Codout.Framework.Mongo/Codout.Framework.Mongo.csproj +++ b/Codout.Framework.Mongo/Codout.Framework.Mongo.csproj @@ -1,6 +1,7 @@  + 6.2.2 Implementação da interface Codout.Framework.Data para MongoDB Codout;Framework;ORM;DAL;MongoDB;Repository;UnitOfWork; true diff --git a/Codout.Framework.Mongo/MongoUnitOfWork.cs b/Codout.Framework.Mongo/MongoUnitOfWork.cs index 109a21c..8018348 100644 --- a/Codout.Framework.Mongo/MongoUnitOfWork.cs +++ b/Codout.Framework.Mongo/MongoUnitOfWork.cs @@ -9,7 +9,7 @@ namespace Codout.Framework.Mongo; /// -/// Unit of Work para MongoDB com suporte a transa��es (requer replica set) +/// Unit of Work para MongoDB com suporte a transações (requer replica set) /// public class MongoUnitOfWork : IUnitOfWork { @@ -32,7 +32,7 @@ public void BeginTransaction() public void BeginTransaction(IsolationLevel isolationLevel) { if (_session != null) - throw new InvalidOperationException("Uma transa��o j� est� em andamento."); + throw new InvalidOperationException("Uma transação já está em andamento."); _session = _client.StartSession(); @@ -46,7 +46,7 @@ public void BeginTransaction(IsolationLevel isolationLevel) public void Commit() { if (_session == null || !_session.IsInTransaction) - throw new InvalidOperationException("Nenhuma transa��o ativa para commit. Chame BeginTransaction() primeiro."); + throw new InvalidOperationException("Nenhuma transação ativa para commit. Chame BeginTransaction() primeiro."); try { @@ -66,7 +66,7 @@ public void Commit() public void Commit(IsolationLevel isolationLevel) { - // IsolationLevel � definido no BeginTransaction + // IsolationLevel é definido no BeginTransaction Commit(); } @@ -125,7 +125,7 @@ public Task BeginTransactionAsync(CancellationToken cancellationToken = default) public async Task BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default) { if (_session != null) - throw new InvalidOperationException("Uma transa��o j� est� em andamento."); + throw new InvalidOperationException("Uma transação já está em andamento."); _session = await _client.StartSessionAsync(cancellationToken: cancellationToken); @@ -139,7 +139,7 @@ public async Task BeginTransactionAsync(IsolationLevel isolationLevel, Cancellat public async Task CommitAsync(CancellationToken cancellationToken = default) { if (_session == null || !_session.IsInTransaction) - throw new InvalidOperationException("Nenhuma transa��o ativa para commit. Chame BeginTransactionAsync() primeiro."); + throw new InvalidOperationException("Nenhuma transação ativa para commit. Chame BeginTransactionAsync() primeiro."); try { @@ -251,7 +251,7 @@ public async ValueTask DisposeAsync() #endregion /// - /// Obt�m a sess�o MongoDB atual (para uso em opera��es dentro da transa��o) + /// Obtém a sessão MongoDB atual (para uso em operações dentro da transação) /// public IClientSessionHandle? CurrentSession => _session; } diff --git a/Codout.Framework.Mongo/README.md b/Codout.Framework.Mongo/README.md index 1eb057a..411a884 100644 --- a/Codout.Framework.Mongo/README.md +++ b/Codout.Framework.Mongo/README.md @@ -1,18 +1,18 @@ # Codout.Framework.Mongo -Implementa��o do padr�o Repository e Unit of Work para MongoDB. +Implementação do padrão Repository e Unit of Work para MongoDB. ## ?? Recursos - ? **Repository Pattern** com MongoDB -- ? **Unit of Work Pattern** com suporte a transa��es (replica set) +- ? **Unit of Work Pattern** com suporte a transações (replica set) - ? **Async/await completo** com CancellationToken -- ? **M�todos auxiliares** (FirstOrDefault, Any, Count, ToList) +- ? **Métodos auxiliares** (FirstOrDefault, Any, Count, ToList) - ? **IAsyncDisposable** suportado - ? **Nullable Reference Types** habilitado -- ? **Documenta��o XML** completa +- ? **Documentação XML** completa -## ?? Instala��o +## ?? Instalação ```bash dotnet add package Codout.Framework.Mongo @@ -20,14 +20,14 @@ dotnet add package Codout.Framework.Mongo ## ?? Requisitos -### Transa��es MongoDB -Para usar transa��es (Unit of Work), voc� precisa: +### Transações MongoDB +Para usar transações (Unit of Work), você precisa: - ? MongoDB 4.0+ com **replica set** configurado - ? Ou MongoDB 4.2+ com **sharded cluster** -**Nota**: Transa��es N�O funcionam em MongoDB standalone. +**Nota**: Transações NÃO funcionam em MongoDB standalone. -## ?? Configura��o +## ?? Configuração ### appsettings.json @@ -69,7 +69,7 @@ services.AddScoped(); services.AddScoped(); ``` -## ?? Uso B�sico +## ?? Uso Básico ### Entidades @@ -124,7 +124,7 @@ public class ProductRepository : MongoRepository } ``` -### Unit of Work (com Transa��es) +### Unit of Work (com Transações) ```csharp public class ProductService @@ -162,7 +162,7 @@ var product = await _unitOfWork.InTransactionAsync(async () => }, ct); ``` -## ?? Opera��es Dispon�veis +## ?? Operações Disponíveis ### Query Methods @@ -176,10 +176,10 @@ var active = repository.Where(p => p.IsActive); // Read-only (mesma performance no MongoDB) var readOnly = repository.AllReadOnly(); -// Pagina��o +// Paginação var paged = repository.WherePaged(p => p.IsActive, out int total, index: 0, size: 20); -// Get �nico +// Get único var product = await repository.GetAsync(p => p.Id == id, ct); // FirstOrDefault @@ -224,26 +224,26 @@ var merged = await repository.MergeAsync(product, ct); var refreshed = await repository.RefreshAsync(product, ct); ``` -## ?? Limita��es do MongoDB +## ?? Limitações do MongoDB ### 1. Includes (Relacionamentos) -MongoDB n�o suporta `Include` nativo como EF Core: +MongoDB não suporta `Include` nativo como EF Core: ```csharp -// ? N�o funciona como esperado +// ? Não funciona como esperado var products = repository.IncludeMany(p => p.Category); -// ? Use agrega��es ou lookups do MongoDB +// ? Use agregações ou lookups do MongoDB var collection = context.GetCollection(); var productsWithCategory = await collection.Aggregate() .Lookup("categories", "categoryId", "_id", "category") .ToListAsync(ct); ``` -### 2. Transa��es +### 2. Transações -Transa��es requerem replica set: +Transações requerem replica set: ```bash # Configurar replica set local (desenvolvimento) @@ -256,13 +256,13 @@ mongosh ### 3. IQueryable Limitado -O driver MongoDB suporta LINQ, mas n�o todos os operadores: +O driver MongoDB suporta LINQ, mas não todos os operadores: ```csharp // ? Funciona var products = repository.Where(p => p.Price > 100 && p.IsActive); -// ?? Pode n�o funcionar +// ?? Pode não funcionar var products = repository.Where(p => p.Name.StartsWith("A") || p.Name.EndsWith("Z")); // ? Alternativa: usar filtros do MongoDB @@ -272,7 +272,7 @@ var filter = Builders.Filter.Or( ); ``` -## ?? Opera��es com CancellationToken +## ?? Operações com CancellationToken ```csharp var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); @@ -285,7 +285,7 @@ try } catch (OperationCanceledException) { - Console.WriteLine("Opera��o cancelada pelo timeout"); + Console.WriteLine("Operação cancelada pelo timeout"); } ``` @@ -302,21 +302,21 @@ catch (OperationCanceledException) ??? Product.cs ``` -## ?? Melhores Pr�ticas +## ?? Melhores Práticas 1. **Use ObjectId para IDs**: MongoDB funciona melhor com ObjectId -2. **Configure �ndices**: Use atributos `[BsonIndex]` ou configure via c�digo -3. **Use CancellationToken**: Sempre em opera��es async -4. **Transa��es apenas quando necess�rio**: T�m overhead de performance -5. **Evite queries muito complexas**: Use agrega��es do MongoDB diretamente -6. **Configure Write Concern**: Para garantir persist�ncia em replica set -7. **Use await using**: Para dispose autom�tico do UnitOfWork +2. **Configure índices**: Use atributos `[BsonIndex]` ou configure via código +3. **Use CancellationToken**: Sempre em operações async +4. **Transações apenas quando necessário**: Têm overhead de performance +5. **Evite queries muito complexas**: Use agregações do MongoDB diretamente +6. **Configure Write Concern**: Para garantir persistência em replica set +7. **Use await using**: Para dispose automático do UnitOfWork 8. **Valide ObjectId**: Antes de fazer queries por ID -## ?? �ndices +## ?? Índices ```csharp -// Via c�digo na configura��o +// Via código na configuração var collection = database.GetCollection("products"); var indexKeysDefinition = Builders.IndexKeys @@ -332,38 +332,38 @@ await collection.Indexes.CreateOneAsync( ## ?? Novidades v10.0 ### Novos Recursos -- ? **MongoUnitOfWork** criado do zero com transa��es -- ? **M�todos auxiliares**: `FirstOrDefaultAsync`, `AnyAsync`, `CountAsync`, `ToListAsync` +- ? **MongoUnitOfWork** criado do zero com transações +- ? **Métodos auxiliares**: `FirstOrDefaultAsync`, `AnyAsync`, `CountAsync`, `ToListAsync` - ? **IAsyncDisposable** implementado -- ? **Sobrecargas com CancellationToken** em todos m�todos async -- ? **Valida��es** com `ArgumentNullException.ThrowIfNull` +- ? **Sobrecargas com CancellationToken** em todos métodos async +- ? **Validações** com `ArgumentNullException.ThrowIfNull` ### Melhorias -- ? **Performance** otimizada para opera��es batch -- ?? **Documenta��o XML** completa +- ? **Performance** otimizada para operações batch +- ?? **Documentação XML** completa - ?? **Nullable reference types** habilitado - ?? **Thread-safe** implementation -### Corre��es -- ?? **GetIdValue** agora suporta m�ltiplos tipos de ID +### Correções +- ?? **GetIdValue** agora suporta múltiplos tipos de ID - ?? **Exists** implementado corretamente - ?? **Load/Refresh** agora funcionam adequadamente ## ?? Links Relacionados -- [Codout.Framework.Data](../Codout.Framework.Data/README.md) - Abstra��es base -- [Codout.Framework.EF](../Codout.Framework.EF/README.md) - Implementa��o Entity Framework -- [Codout.Framework.NH](../Codout.Framework.NH/README.md) - Implementa��o NHibernate +- [Codout.Framework.Data](../Codout.Framework.Data/README.md) - Abstrações base +- [Codout.Framework.EF](../Codout.Framework.EF/README.md) - Implementação Entity Framework +- [Codout.Framework.NH](../Codout.Framework.NH/README.md) - Implementação NHibernate - [MongoDB Driver .NET](https://www.mongodb.com/docs/drivers/csharp/current/) - [MongoDB Transactions](https://www.mongodb.com/docs/manual/core/transactions/) -## ?? Licen�a +## ?? Licença Propriedade da Codout --- -**Vers�o:** 10.0.0 -**Status:** Est�vel para produ��o +**Versão:** 10.0.0 +**Status:** Estável para produção **Target:** .NET 10 **MongoDB Driver:** 3.5.1 diff --git a/Codout.Framework.NH/Codout.Framework.NH.csproj b/Codout.Framework.NH/Codout.Framework.NH.csproj index af7bbe6..ad1f438 100644 --- a/Codout.Framework.NH/Codout.Framework.NH.csproj +++ b/Codout.Framework.NH/Codout.Framework.NH.csproj @@ -1,6 +1,7 @@  + 6.2.2 Implementação da interface Codout.Framework.Data para NHibernate Codout;Framework;ORM;DAL;NHibernate;Repository;UnitOfWork; true diff --git a/Codout.Framework.NH/README.md b/Codout.Framework.NH/README.md index 72d2380..00eceaa 100644 --- a/Codout.Framework.NH/README.md +++ b/Codout.Framework.NH/README.md @@ -1,25 +1,25 @@ # Codout.Framework.NH -Implementa��o do padr�o Repository e Unit of Work para NHibernate. +Implementação do padrão Repository e Unit of Work para NHibernate. ## ?? Recursos - ? **Repository Pattern** com NHibernate -- ? **Unit of Work Pattern** com transa��es +- ? **Unit of Work Pattern** com transações - ? **Async/await completo** com CancellationToken -- ? **M�todos auxiliares** (FirstOrDefault, Any, Count, ToList) +- ? **Métodos auxiliares** (FirstOrDefault, Any, Count, ToList) - ? **FluentNHibernate** suportado - ? **IAsyncDisposable** suportado - ? **Nullable Reference Types** habilitado -- ? **Documenta��o XML** completa +- ? **Documentação XML** completa -## ?? Instala��o +## ?? Instalação ```bash dotnet add package Codout.Framework.NH ``` -## ?? Configura��o +## ?? Configuração ### appsettings.json @@ -67,7 +67,7 @@ services.AddScoped(sp => services.AddScoped(); ``` -## ?? Uso B�sico +## ?? Uso Básico ### Entidades @@ -144,7 +144,7 @@ public class ProductRepository : NHRepository } ``` -### Unit of Work (com Transa��es) +### Unit of Work (com Transações) ```csharp public class ProductService @@ -182,7 +182,7 @@ var product = await _unitOfWork.InTransactionAsync(async () => }, ct); ``` -## ?? Opera��es Dispon�veis +## ?? Operações Disponíveis ### Query Methods @@ -199,10 +199,10 @@ var active = repository.Where(p => p.IsActive); // Read-only com filtro var activeReadOnly = repository.WhereReadOnly(p => p.IsActive); -// Pagina��o +// Paginação var paged = repository.WherePaged(p => p.IsActive, out int total, index: 0, size: 20); -// Get �nico +// Get único var product = await repository.GetAsync(p => p.Id == id, ct); // FirstOrDefault @@ -217,7 +217,7 @@ var count = await repository.CountAsync(p => p.IsActive, ct); // ToList var list = await repository.ToListAsync(p => p.Price > 100, ct); -// Load (retorna proxy lazy - n�o � async nativo) +// Load (retorna proxy lazy - não é async nativo) var proxy = repository.Load(id); ``` @@ -248,10 +248,10 @@ var refreshed = await repository.RefreshAsync(product, ct); ## ?? Eager Loading -### NHibernate n�o suporta Include como EF Core +### NHibernate não suporta Include como EF Core ```csharp -// ? N�o funciona +// ? Não funciona var products = repository.IncludeMany(p => p.Category); // ? Use Fetch no LINQ @@ -277,7 +277,7 @@ var products = session.CreateCriteria() .List(); ``` -## ??? Mapeamento Avan�ado +## ??? Mapeamento Avançado ### Relacionamentos @@ -324,7 +324,7 @@ public class ProductMap : ClassMap ## ?? Session Management -### Acesso direto � Session +### Acesso direto à Session ```csharp public class ProductRepository : NHRepository @@ -345,7 +345,7 @@ public class ProductRepository : NHRepository } ``` -## ?? Considera��es NHibernate +## ?? Considerações NHibernate ### 1. Propriedades Virtuais @@ -358,7 +358,7 @@ public class Product public virtual Category Category { get; set; } } -// ? Errado - n�o permite lazy loading +// ? Errado - não permite lazy loading public class Product { public int Id { get; set; } @@ -369,10 +369,10 @@ public class Product ### 2. Flush vs Commit ```csharp -// Flush persiste no banco mas n�o comita a transa��o +// Flush persiste no banco mas não comita a transação await Session.FlushAsync(ct); -// Commit faz flush + commit da transa��o +// Commit faz flush + commit da transação await unitOfWork.CommitAsync(ct); ``` @@ -393,16 +393,16 @@ await repository.UpdateAsync(merged, ct); ### 4. Load vs Get ```csharp -// Load - retorna proxy, lan�a exce��o se n�o existir quando acessado -var proxy = repository.Load(id); // N�o acessa o banco ainda +// Load - retorna proxy, lança exceção se não existir quando acessado +var proxy = repository.Load(id); // Não acessa o banco ainda var name = proxy.Name; // Acessa o banco aqui -// Get - retorna null se n�o existir +// Get - retorna null se não existir var product = await repository.GetAsync(id, ct); // Acessa o banco imediatamente -if (product == null) { /* n�o existe */ } +if (product == null) { /* não existe */ } ``` -## ?? Opera��es com CancellationToken +## ?? Operações com CancellationToken ```csharp var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); @@ -415,37 +415,37 @@ try } catch (OperationCanceledException) { - Console.WriteLine("Opera��o cancelada pelo timeout"); + Console.WriteLine("Operação cancelada pelo timeout"); } ``` -## ?? Melhores Pr�ticas +## ?? Melhores Práticas 1. **Use propriedades virtual**: Permite lazy loading e proxies 2. **Configure Cascade corretamente**: Evite orphan deletions acidentais -3. **Use CancellationToken**: Sempre em opera��es async +3. **Use CancellationToken**: Sempre em operações async 4. **Flush antes de queries**: Se precisar dos dados persistidos 5. **Evite N+1**: Use Fetch/FetchMany para eager loading -6. **Configure �ndices**: No banco ou via atributos -7. **Use Stateless Session**: Para opera��es batch de alto volume -8. **Use await using**: Para dispose autom�tico do UnitOfWork +6. **Configure índices**: No banco ou via atributos +7. **Use Stateless Session**: Para operações batch de alto volume +8. **Use await using**: Para dispose automático do UnitOfWork 9. **Evite lazy loading em loops**: Carregue dados antecipadamente -10. **Configure cache de segundo n�vel**: Para performance +10. **Configure cache de segundo nível**: Para performance -## ?? �ndices +## ?? Índices ```csharp public class ProductMap : ClassMap { public ProductMap() { - // �ndice �nico + // Índice único Map(x => x.Name) .Not.Nullable() .Length(200) .UniqueKey("UK_Product_Name"); - // �ndice composto + // Índice composto Map(x => x.CategoryId).Index("IX_Product_Category_Active"); Map(x => x.IsActive).Index("IX_Product_Category_Active"); } @@ -455,39 +455,39 @@ public class ProductMap : ClassMap ## ?? Novidades v10.0 ### Novos Recursos -- ? **M�todos auxiliares**: `FirstOrDefaultAsync`, `AnyAsync`, `CountAsync`, `ToListAsync` +- ? **Métodos auxiliares**: `FirstOrDefaultAsync`, `AnyAsync`, `CountAsync`, `ToListAsync` - ? **IAsyncDisposable** implementado no UnitOfWork -- ? **Sobrecargas com CancellationToken** em todos m�todos async -- ? **Valida��es** com `ArgumentNullException.ThrowIfNull` -- ? **Flush expl�cito** antes de commit para consist�ncia +- ? **Sobrecargas com CancellationToken** em todos métodos async +- ? **Validações** com `ArgumentNullException.ThrowIfNull` +- ? **Flush explícito** antes de commit para consistência ### Melhorias - ? **Performance** otimizada em batch operations -- ?? **Documenta��o XML** completa +- ?? **Documentação XML** completa - ?? **Nullable reference types** habilitado - ?? **Thread-safe** implementation -### Corre��es -- ?? **Transa��es** agora fazem flush antes de commit -- ?? **Dispose** correto de transa��es em exce��es +### Correções +- ?? **Transações** agora fazem flush antes de commit +- ?? **Dispose** correto de transações em exceções - ?? **LoadAsync** implementado corretamente ## ?? Links Relacionados -- [Codout.Framework.Data](../Codout.Framework.Data/README.md) - Abstra��es base -- [Codout.Framework.EF](../Codout.Framework.EF/README.md) - Implementa��o Entity Framework -- [Codout.Framework.Mongo](../Codout.Framework.Mongo/README.md) - Implementa��o MongoDB +- [Codout.Framework.Data](../Codout.Framework.Data/README.md) - Abstrações base +- [Codout.Framework.EF](../Codout.Framework.EF/README.md) - Implementação Entity Framework +- [Codout.Framework.Mongo](../Codout.Framework.Mongo/README.md) - Implementação MongoDB - [NHibernate Documentation](https://nhibernate.info/doc/) - [FluentNHibernate](https://github.com/nhibernate/fluent-nhibernate) -## ?? Licen�a +## ?? Licença Propriedade da Codout --- -**Vers�o:** 10.0.0 -**Status:** Est�vel para produ��o +**Versão:** 10.0.0 +**Status:** Estável para produção **Target:** .NET 10 **NHibernate:** 5.6.0 **FluentNHibernate:** 3.4.1 diff --git a/Codout.Framework.Storage.Azure/Codout.Framework.Storage.Azure.csproj b/Codout.Framework.Storage.Azure/Codout.Framework.Storage.Azure.csproj index 2b733b0..a5e2e3b 100644 --- a/Codout.Framework.Storage.Azure/Codout.Framework.Storage.Azure.csproj +++ b/Codout.Framework.Storage.Azure/Codout.Framework.Storage.Azure.csproj @@ -1,6 +1,7 @@ + 6.2.2 latest enable Codout Framework Storage Azure diff --git a/Codout.Framework.Storage/Codout.Framework.Storage.csproj b/Codout.Framework.Storage/Codout.Framework.Storage.csproj index a39dc1f..4a17024 100644 --- a/Codout.Framework.Storage/Codout.Framework.Storage.csproj +++ b/Codout.Framework.Storage/Codout.Framework.Storage.csproj @@ -1,6 +1,7 @@ + 6.2.2 latest enable Codout Framework Storage diff --git a/Codout.Framework.Storage/README.md b/Codout.Framework.Storage/README.md index 140dc76..3112031 100644 --- a/Codout.Framework.Storage/README.md +++ b/Codout.Framework.Storage/README.md @@ -1,24 +1,24 @@ # Codout.Framework.Storage -Abstra��o cloud-agnostic para opera��es de armazenamento de arquivos (Azure, AWS S3, File System). +Abstração cloud-agnostic para operações de armazenamento de arquivos (Azure, AWS S3, File System). ## ?? Recursos -- ? **Interface unificada** para m�ltiplos provedores +- ? **Interface unificada** para múltiplos provedores - ? **Async/await** com CancellationToken - ? **Metadata support** para arquivos -- ? **SAS tokens** para acesso tempor�rio +- ? **SAS tokens** para acesso temporário - ? **List operations** para descoberta de arquivos -- ? **Batch operations** para deletar m�ltiplos arquivos +- ? **Batch operations** para deletar múltiplos arquivos - ? **Progress reporting** para uploads -- ? **Exce��es customizadas** para tratamento espec�fico +- ? **Exceções customizadas** para tratamento específico - ? **CDN support** para URLs otimizadas - ? **Thread-safe** implementations -## ?? Instala��o +## ?? Instalação ```bash -# Abstra��es +# Abstrações dotnet add package Codout.Framework.Storage # Azure Blob Storage @@ -31,7 +31,7 @@ dotnet add package Codout.Framework.Storage.AWS dotnet add package Codout.Framework.Storage.FileSystem ``` -## ?? Configura��o +## ?? Configuração ### Azure Blob Storage @@ -43,10 +43,10 @@ dotnet add package Codout.Framework.Storage.FileSystem } } -// Program.cs - B�sico +// Program.cs - Básico services.AddAzureStorage(configuration); -// Program.cs - Avan�ado +// Program.cs - Avançado services.AddAzureStorage(options => { options.ConnectionString = configuration.GetConnectionString("AzureStorage"); @@ -59,7 +59,7 @@ services.AddAzureStorage(options => }); ``` -## ?? Uso B�sico +## ?? Uso Básico ### Upload @@ -119,7 +119,7 @@ public async Task GetStreamAsync(string fileName, CancellationToken ct = // Deletar um arquivo await _storage.DeleteAsync("documents", "file.pdf", ct); -// Deletar m�ltiplos arquivos +// Deletar múltiplos arquivos var files = new[] { "file1.pdf", "file2.pdf", "file3.pdf" }; await _storage.DeleteManyAsync("documents", files, ct); ``` @@ -165,17 +165,17 @@ var customData = new Dictionary await _storage.SetMetadataAsync("documents", "file.pdf", customData, ct); ``` -### SAS Tokens (Acesso Tempor�rio) +### SAS Tokens (Acesso Temporário) ```csharp -// Gerar URL com acesso tempor�rio de 1 hora +// Gerar URL com acesso temporário de 1 hora var sasUri = await _storage.GetSasUriAsync("documents", "file.pdf", TimeSpan.FromHours(1), ct); // Enviar ao cliente return Ok(new { downloadUrl = sasUri.ToString() }); ``` -### Verificar Exist�ncia +### Verificar Existência ```csharp if (await _storage.ExistsAsync("documents", "file.pdf", ct)) @@ -184,7 +184,7 @@ if (await _storage.ExistsAsync("documents", "file.pdf", ct)) } ``` -## ?? Opera��es Avan�adas +## ?? Operações Avançadas ### Upload com Progress Bar @@ -201,7 +201,7 @@ public async Task UploadWithProgressBarAsync(Stream file, string fileName) } ``` -### Tratamento de Erros Espec�ficos +### Tratamento de Erros Específicos ```csharp try @@ -210,7 +210,7 @@ try } catch (StorageNotFoundException ex) { - // Arquivo n�o encontrado + // Arquivo não encontrado return NotFound($"File not found: {ex.FileName}"); } catch (StorageContainerException ex) @@ -220,20 +220,20 @@ catch (StorageContainerException ex) } catch (StorageException ex) { - // Erro gen�rico de storage + // Erro genérico de storage return StatusCode(500, $"Storage error: {ex.Message}"); } ``` -### M�ltiplos Provedores +### Múltiplos Provedores ```csharp -// Registrar m�ltiplos storage providers +// Registrar múltiplos storage providers services.AddAzureStorage(azureOptions); services.AddKeyedSingleton("aws", new AwsStorage(awsOptions)); services.AddKeyedSingleton("local", new FileSystemStorage(fsOptions)); -// Usar espec�fico +// Usar específico public class FileService { private readonly IStorage _primaryStorage; @@ -281,39 +281,39 @@ public class StorageMetadata } ``` -## ?? Melhores Pr�ticas +## ?? Melhores Práticas -1. **Use CancellationToken** em todas opera��es async +1. **Use CancellationToken** em todas operações async 2. **Use GetStreamAsync** em vez de DownloadAsync para arquivos grandes (streaming) -3. **Implemente retry logic** para opera��es cr�ticas -4. **Use SAS tokens** para acesso tempor�rio em vez de URLs p�blicas +3. **Implemente retry logic** para operações críticas +4. **Use SAS tokens** para acesso temporário em vez de URLs públicas 5. **Configure CDN** para melhor performance de leitura -6. **Use metadata** para armazenar informa��es contextuais +6. **Use metadata** para armazenar informações contextuais 7. **Valide nomes de arquivos** antes do upload 8. **Implemente progress reporting** para uploads grandes -9. **Use batch operations** para deletar m�ltiplos arquivos -10. **Trate exce��es espec�ficas** (`StorageNotFoundException`, etc.) +9. **Use batch operations** para deletar múltiplos arquivos +10. **Trate exceções específicas** (`StorageNotFoundException`, etc.) ## ?? Novidades v10.0 - ? **Nova interface IStorage** com naming convention async - ? **Metadata support** completo -- ? **SAS tokens** para acesso tempor�rio +- ? **SAS tokens** para acesso temporário - ? **List operations** com prefixo -- ? **Batch delete** para m�ltiplos arquivos +- ? **Batch delete** para múltiplos arquivos - ? **Progress reporting** em uploads -- ? **Exce��es customizadas** tipadas +- ? **Exceções customizadas** tipadas - ? **CDN support** integrado - ? **Thread-safe** lazy loading -- ? **Extens�es DI** fluentes +- ? **Extensões DI** fluentes - ? **Nullable reference types** -## ?? Licen�a +## ?? Licença Propriedade da Codout --- -**Vers�o:** 10.0.0 -**Status:** Est�vel para produ��o +**Versão:** 10.0.0 +**Status:** Estável para produção **Target:** .NET 10 diff --git a/Codout.Image.Extensions/Codout.Image.Extensions.csproj b/Codout.Image.Extensions/Codout.Image.Extensions.csproj index 28d69f6..835eb24 100644 --- a/Codout.Image.Extensions/Codout.Image.Extensions.csproj +++ b/Codout.Image.Extensions/Codout.Image.Extensions.csproj @@ -1,6 +1,7 @@  + 6.2.2 Biblioteca de funções para imagens Codout;Framework;Images; diff --git a/Codout.Mailer.AWS/Codout.Mailer.AWS.csproj b/Codout.Mailer.AWS/Codout.Mailer.AWS.csproj index ba33cc2..db259c7 100644 --- a/Codout.Mailer.AWS/Codout.Mailer.AWS.csproj +++ b/Codout.Mailer.AWS/Codout.Mailer.AWS.csproj @@ -1,6 +1,7 @@  + 6.2.2 Sender da Amazon Simple Email Service para envio de E-mails utilizando a biblioteca Codout.Mailer Codout;Framework;Mail;Email;Mailer;SendGrid; diff --git a/Codout.Mailer.Razor/Codout.Mailer.Razor.csproj b/Codout.Mailer.Razor/Codout.Mailer.Razor.csproj index 23ee6b8..745b035 100644 --- a/Codout.Mailer.Razor/Codout.Mailer.Razor.csproj +++ b/Codout.Mailer.Razor/Codout.Mailer.Razor.csproj @@ -1,7 +1,8 @@ - Implementa��o do template engine para Codout.Mailer utilizando a engine Razor nativa do ASP.NET Core + 6.2.2 + Implementação do template engine para Codout.Mailer utilizando a engine Razor nativa do ASP.NET Core Codout;Framework;Mail;Email;Mailer;Razor; diff --git a/Codout.Mailer.SendGrid/Codout.Mailer.SendGrid.csproj b/Codout.Mailer.SendGrid/Codout.Mailer.SendGrid.csproj index f2f9668..a3834f0 100644 --- a/Codout.Mailer.SendGrid/Codout.Mailer.SendGrid.csproj +++ b/Codout.Mailer.SendGrid/Codout.Mailer.SendGrid.csproj @@ -1,6 +1,7 @@  + 6.2.2 Sender da SendGrid para envio de E-mails utilizando a biblioteca Codout.Mailer Codout;Framework;Mail;Email;Mailer;SendGrid; diff --git a/Codout.Mailer/Codout.Mailer.csproj b/Codout.Mailer/Codout.Mailer.csproj index bb1feab..7df4e7b 100644 --- a/Codout.Mailer/Codout.Mailer.csproj +++ b/Codout.Mailer/Codout.Mailer.csproj @@ -1,6 +1,7 @@  + 6.2.2 Biblioteca extensível para envio de e-mails com suporte a múltiplos providers (SendGrid, AWS SES), health checks e observabilidade. O template engine é plugável via ITemplateEngine (veja Codout.Mailer.Razor). Codout;Framework;Mail;Email;Mailer; diff --git a/Codout.Mailer/Services/MailerHealthCheck.cs b/Codout.Mailer/Services/MailerHealthCheck.cs index 543ebf7..77f3545 100644 --- a/Codout.Mailer/Services/MailerHealthCheck.cs +++ b/Codout.Mailer/Services/MailerHealthCheck.cs @@ -12,7 +12,7 @@ public async Task CheckHealthAsync(HealthCheckContext context { try { - // Implementar verifica��o de conectividade + // Implementar verificação de conectividade return HealthCheckResult.Healthy("Mailer service is healthy"); } catch (Exception ex) diff --git a/Codout.Multitenancy/Codout.Multitenancy.csproj b/Codout.Multitenancy/Codout.Multitenancy.csproj index d0d787e..64b5f8d 100644 --- a/Codout.Multitenancy/Codout.Multitenancy.csproj +++ b/Codout.Multitenancy/Codout.Multitenancy.csproj @@ -1,6 +1,7 @@ + 6.2.2 Modulo Multitenancy da Codout para aplicações Asp.net Core Codout;Framework diff --git a/Codout.Multitenancy/Softprime.Multitenancy.csproj b/Codout.Multitenancy/Softprime.Multitenancy.csproj index 20edddd..dd8d928 100644 --- a/Codout.Multitenancy/Softprime.Multitenancy.csproj +++ b/Codout.Multitenancy/Softprime.Multitenancy.csproj @@ -1,6 +1,7 @@ + 6.2.2 netstandard2.0 diff --git a/Directory.Build.props b/Directory.Build.props index 2d532df..4f0b757 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,9 @@ latest - 6.2.2 + Clovis Coli Jr Codout Codout diff --git a/src/NetCore/Codout.Framework.NetCore.Repository.Cosmos/Codout.Framework.NetCore.Repository.Cosmos.csproj b/src/NetCore/Codout.Framework.NetCore.Repository.Cosmos/Codout.Framework.NetCore.Repository.Cosmos.csproj index 6a22122..7c3dde8 100644 --- a/src/NetCore/Codout.Framework.NetCore.Repository.Cosmos/Codout.Framework.NetCore.Repository.Cosmos.csproj +++ b/src/NetCore/Codout.Framework.NetCore.Repository.Cosmos/Codout.Framework.NetCore.Repository.Cosmos.csproj @@ -1,6 +1,7 @@ + 6.2.2 netcoreapp2.0 true Marcelo & Clovis diff --git a/src/NetCore/Codout.Framework.NetCore.Repository.DocumentDB/Codout.Framework.NetCore.Repository.DocumentDB.csproj b/src/NetCore/Codout.Framework.NetCore.Repository.DocumentDB/Codout.Framework.NetCore.Repository.DocumentDB.csproj index 64e9f4f..d736052 100644 --- a/src/NetCore/Codout.Framework.NetCore.Repository.DocumentDB/Codout.Framework.NetCore.Repository.DocumentDB.csproj +++ b/src/NetCore/Codout.Framework.NetCore.Repository.DocumentDB/Codout.Framework.NetCore.Repository.DocumentDB.csproj @@ -1,6 +1,7 @@ + 6.2.2 netcoreapp2.0 diff --git a/src/Security/Codout.Security.Argon2/Codout.Security.Argon2.csproj b/src/Security/Codout.Security.Argon2/Codout.Security.Argon2.csproj index 3ba324a..1f85499 100644 --- a/src/Security/Codout.Security.Argon2/Codout.Security.Argon2.csproj +++ b/src/Security/Codout.Security.Argon2/Codout.Security.Argon2.csproj @@ -1,6 +1,7 @@  + 6.2.2 net10.0 enable enable diff --git a/src/Security/Codout.Security.Bcrypt/Codout.Security.Bcrypt.csproj b/src/Security/Codout.Security.Bcrypt/Codout.Security.Bcrypt.csproj index 521c74e..1818b4a 100644 --- a/src/Security/Codout.Security.Bcrypt/Codout.Security.Bcrypt.csproj +++ b/src/Security/Codout.Security.Bcrypt/Codout.Security.Bcrypt.csproj @@ -1,6 +1,7 @@  + 6.2.2 net10.0 enable enable diff --git a/src/Security/Codout.Security.Core/Codout.Security.Core.csproj b/src/Security/Codout.Security.Core/Codout.Security.Core.csproj index 5831e53..dd59ce2 100644 --- a/src/Security/Codout.Security.Core/Codout.Security.Core.csproj +++ b/src/Security/Codout.Security.Core/Codout.Security.Core.csproj @@ -1,6 +1,7 @@  + 6.2.2 net10.0 enable enable diff --git a/src/Security/Codout.Security.Scrypt/Codout.Security.Scrypt.csproj b/src/Security/Codout.Security.Scrypt/Codout.Security.Scrypt.csproj index 26f553a..b58745b 100644 --- a/src/Security/Codout.Security.Scrypt/Codout.Security.Scrypt.csproj +++ b/src/Security/Codout.Security.Scrypt/Codout.Security.Scrypt.csproj @@ -1,6 +1,7 @@  + 6.2.2 net10.0 enable enable