diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..d1afcf5
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,30 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(dotnet restore:*)",
+ "Bash(dotnet build:*)",
+ "Bash(dotnet test:*)",
+ "Bash(dotnet:*)",
+ "Bash(git status:*)",
+ "Bash(git add:*)",
+ "Bash(git commit:*)",
+ "Bash(sed 's/^A\\\\t//')",
+ "Bash(grep \"\\\\.csproj$\")",
+ "Bash(sed 's/^D\\\\t//')",
+ "Bash(git stash:*)",
+ "Bash(git pull:*)",
+ "Bash(python3 -c \":*)",
+ "Bash(for pkg:*)",
+ "Bash(do)",
+ "Bash(echo \"=== $pkg ===\")",
+ "Read(//c/Users/najaf/.nuget/packages/$pkg/**)",
+ "Bash(done)",
+ "Bash(git push:*)",
+ "Bash(git checkout:*)",
+ "Bash(find /c/Work/Projects/Published/DataFuse -name *.md -type f)",
+ "Bash(ls:*)",
+ "Bash(find /c/Work/Projects/Published/DataFuse/src -name *.cs -type f)",
+ "Bash(xargs grep:*)"
+ ]
+ }
+}
diff --git a/.github/workflows/Build-Master.yml b/.github/workflows/Build-Master.yml
index 4e1915a..847bb27 100644
--- a/.github/workflows/Build-Master.yml
+++ b/.github/workflows/Build-Master.yml
@@ -10,17 +10,22 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 6.0.x
+ dotnet-version: |
+ 8.0.x
+ 9.0.x
+ 10.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- - name: Test
- run: dotnet test --no-build --verbosity normal
+ - name: Unit Tests
+ run: dotnet test --no-build --verbosity normal --filter "FullyQualifiedName~Unit"
+ - name: Integration Tests
+ run: dotnet test --no-build --verbosity normal --filter "FullyQualifiedName~Integration"
run-Lint:
runs-on: ubuntu-latest
@@ -28,7 +33,7 @@ jobs:
github-token: '${{ secrets.GITHUB_TOKEN }}'
steps:
- name: Step-01 Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Step-02 Lint Code Base
diff --git a/.github/workflows/Master-Build.yml b/.github/workflows/Master-Build.yml
deleted file mode 100644
index fb70f0d..0000000
--- a/.github/workflows/Master-Build.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# This workflow will build a .NET project
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
-
-name: build-master
-
-on:
- push:
- branches: [ "master" ]
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Setup .NET
- uses: actions/setup-dotnet@v3
- with:
- dotnet-version: 6.0.x
- - name: Restore dependencies
- run: dotnet restore
- - name: Build
- run: dotnet build --no-restore
- - name: Test
- run: dotnet test --no-build --verbosity normal
-
- run-Lint:
- runs-on: ubuntu-latest
- env:
- github-token: '${{ secrets.GITHUB_TOKEN }}'
- steps:
- - name: Step-01 Checkout code
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- - name: Step-02 Lint Code Base
- uses: github/super-linter@v4
- env:
- VALIDATE_ALL_CODEBASE: false
- FILTER_REGEX_INCLUDE: .*src/.*
- DEFAULT_BRANCH: master
- GITHUB_TOKEN: '${{ env.github-token }}'
diff --git a/.github/workflows/Master-CodeQL.yml b/.github/workflows/Master-CodeQL.yml
index b765a11..fd68322 100644
--- a/.github/workflows/Master-CodeQL.yml
+++ b/.github/workflows/Master-CodeQL.yml
@@ -13,64 +13,86 @@ name: "Master-CodeQL"
on:
push:
- pull_request:
- types: [opened, reopened, edited, synchronize]
- paths-ignore:
- - "**/*.md"
- - "**/*.gitignore"
- - "**/*.gitattributes"
+ branches: [ "master" ]
schedule:
- - cron: '35 15 * * 2'
+ - cron: '42 7 * * 5'
jobs:
analyze:
- name: Analyze
- runs-on: ubuntu-latest
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
actions: read
contents: read
- security-events: write
strategy:
fail-fast: false
matrix:
- language: [ 'csharp' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
- # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
-
+ include:
+ - language: actions
+ build-mode: none
+ - language: csharp
+ build-mode: none
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
+
+ # Add any setup steps before running the `github/codeql-action/init` action.
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
+ # or others). This is typically only required for manual builds.
+ # - name: Setup runtime (example)
+ # uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
- # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v2
-
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
# âšī¸ Command-line programs to run using the OS shell.
# đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
-
- # If the Autobuild fails above, remove it and uncomment the following three lines.
- # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
-
- # - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
- category: "/language:${{matrix.language}}"
\ No newline at end of file
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/PullRequest-CI.yml b/.github/workflows/PullRequest-CI.yml
index 6d47951..3dea6d5 100644
--- a/.github/workflows/PullRequest-CI.yml
+++ b/.github/workflows/PullRequest-CI.yml
@@ -30,7 +30,7 @@ jobs:
beta_Version: ${{ steps.gitversion.outputs.nuGetVersion }}
branchName: ${{ steps.gitversion.outputs.branchName }}
env:
- working-directory: /home/runner/work/Motley/Motley
+ working-directory: /home/runner/work/DataFuse.Net/DataFuse.Net
steps:
- name: Step-01 Install GitVersion
@@ -39,7 +39,7 @@ jobs:
versionSpec: 5.x
- name: Step-02 Check out Code
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -52,28 +52,35 @@ jobs:
- name: Step-04 Install .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 6.0.x
+ dotnet-version: |
+ 8.0.x
+ 9.0.x
+ 10.0.x
- name: Step-05 Restore dependencies
run: dotnet restore
working-directory: '${{ env.working-directory }}'
- name: Step-06 Build Version (Beta)
- if: ${{ !startsWith(github.head_ref, 'release/')}}
+ if: ('!startsWith(github.ref, ''refs/heads/release'')')
run: dotnet build --configuration Release --no-restore -p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersion }}
working-directory: '${{ env.working-directory }}'
- name: Step-06 Build Version (Release)
- if: ${{ startsWith(github.head_ref, 'release/')}}
+ if: ('startsWith(github.ref, ''refs/heads/release'')')
run: dotnet build --configuration Release --no-restore -p:PackageVersion=${{ steps.gitversion.outputs.MajorMinorPatch }}
working-directory: '${{ env.working-directory }}'
- - name: Step-07 Test Solution
- run: dotnet test --configuration Release --no-build --no-restore --verbosity normal
+ - name: Step-07 Unit Tests
+ run: dotnet test --configuration Release --no-build --no-restore --verbosity normal --filter "FullyQualifiedName~Unit"
+ working-directory: '${{ env.working-directory }}'
+
+ - name: Step-07b Integration Tests
+ run: dotnet test --configuration Release --no-build --no-restore --verbosity normal --filter "FullyQualifiedName~Integration"
working-directory: '${{ env.working-directory }}'
- name: Step-08 Upload Build Artifacts
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: build-artifact
path: ${{env.working-directory}}
@@ -87,10 +94,10 @@ jobs:
env:
github-token: '${{ secrets.GH_Packages }}'
nuget-token: '${{ secrets.NUGET_API_KEY }}'
- working-directory: /home/runner/work/Motley/Motley
+ working-directory: /home/runner/work/DataFuse.Net/DataFuse.Net
steps:
- name: Step-01 Retrieve Build Artifacts
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: build-artifact
path: ${{env.working-directory}}
@@ -104,14 +111,14 @@ jobs:
Release:
name: Release to Nuget
needs: [Package]
- if: ${{ startsWith(github.head_ref, 'release/')}}
+ if: ('startsWith(github.ref, ''refs/heads/release'')')
runs-on: ubuntu-latest
env:
github-token: '${{ secrets.GH_Packages }}'
nuget-token: '${{ secrets.NUGET_API_KEY }}'
- working-directory: /home/runner/work/Motley/Motley
+ working-directory: /home/runner/work/DataFuse.Net/DataFuse.Net
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
@@ -119,15 +126,15 @@ jobs:
# dotnet-version: '6.0.x'
# Publish
- - name: publish Motley package
+ - name: publish DataFuse package
id: publish_nuget
uses: Rebel028/publish-nuget@v2.8.0
with:
# Filepath of the project to be packaged, relative to root of repository
- PROJECT_FILE_PATH: Motley/Motley.csproj
-
+ PROJECT_FILE_PATH: DataFuse/DataFuse.csproj
+
# NuGet package id, used for version detection & defaults to project name
- PACKAGE_NAME: Motley
+ PACKAGE_NAME: DataFuse
# Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
# VERSION_FILE_PATH: Directory.Build.props
diff --git a/.github/workflows/PullRequest-CodeQL.yml b/.github/workflows/PullRequest-CodeQL.yml
index c1b075e..7dcf2f5 100644
--- a/.github/workflows/PullRequest-CodeQL.yml
+++ b/.github/workflows/PullRequest-CodeQL.yml
@@ -12,65 +12,91 @@
name: "PullRequest-CodeQL"
on:
- push:
pull_request:
types: [opened, reopened, edited, synchronize]
paths-ignore:
- "**/*.md"
- "**/*.gitignore"
- - "**/*.gitattributes"
+ - "**/*.gitattributes"
schedule:
- - cron: '35 15 * * 2'
+ - cron: '42 7 * * 5'
jobs:
analyze:
- name: Analyze
- runs-on: ubuntu-latest
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
actions: read
contents: read
- security-events: write
strategy:
fail-fast: false
matrix:
- language: [ 'csharp' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
- # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
-
+ include:
+ - language: actions
+ build-mode: none
+ - language: csharp
+ build-mode: none
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
+
+ # Add any setup steps before running the `github/codeql-action/init` action.
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
+ # or others). This is typically only required for manual builds.
+ # - name: Setup runtime (example)
+ # uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
- # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v2
-
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
# âšī¸ Command-line programs to run using the OS shell.
# đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
-
- # If the Autobuild fails above, remove it and uncomment the following three lines.
- # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
-
- # - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
- category: "/language:${{matrix.language}}"
\ No newline at end of file
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/pages-static.yml b/.github/workflows/pages-static.yml
new file mode 100644
index 0000000..0ba8230
--- /dev/null
+++ b/.github/workflows/pages-static.yml
@@ -0,0 +1,43 @@
+# Simple workflow for deploying static content to GitHub Pages
+name: Deploy static content to Pages
+
+on:
+ # Runs on pushes targeting the default branch
+ push:
+ branches: ["master"]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ # Single deploy job since we're just deploying
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ # Upload entire repository
+ path: '.'
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..e69de29
diff --git a/DataFuse.sln b/DataFuse.sln
new file mode 100644
index 0000000..f63816f
--- /dev/null
+++ b/DataFuse.sln
@@ -0,0 +1,212 @@
+īģŋ
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33516.290
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F41DA3D8-A0E9-4A05-8A35-78313C0F5804}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{AF995FEF-BB94-48D0-B02B-6671DA73056B}"
+ ProjectSection(SolutionItems) = preProject
+ .gitignore = .gitignore
+ index.md = index.md
+ LICENSE.md = LICENSE.md
+ README.md = README.md
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Integration.Tests", "tests\DataFuse.Integration.Tests\DataFuse.Integration.Tests.csproj", "{B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.SQL.Tests", "tests\DataFuse.Adapters.SQL.Tests\DataFuse.Adapters.SQL.Tests.csproj", "{1E319404-8EF0-40A1-A9D7-A404A71A98C4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{39FD806A-D320-43C9-800F-E9D9BCC90623}"
+ ProjectSection(SolutionItems) = preProject
+ .github\workflows\Build-Master.yml = .github\workflows\Build-Master.yml
+ GitVersion.yml = GitVersion.yml
+ .github\workflows\Master-CodeQL.yml = .github\workflows\Master-CodeQL.yml
+ .github\workflows\PullRequest-CI.yml = .github\workflows\PullRequest-CI.yml
+ .github\workflows\PullRequest-CodeQL.yml = .github\workflows\PullRequest-CodeQL.yml
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.EntityFramework.Tests", "tests\DataFuse.Adapters.EntityFramework.Tests\DataFuse.Adapters.EntityFramework.Tests.csproj", "{FE039675-00BE-4DC5-945F-14E7625170D0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Integration", "src\DataFuse.Integration\DataFuse.Integration.csproj", "{4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.Abstraction", "src\DataFuse.Adapters.Abstraction\DataFuse.Adapters.Abstraction.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.EntityFramework", "src\DataFuse.Adapters.EntityFramework\DataFuse.Adapters.EntityFramework.csproj", "{E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.SQL", "src\DataFuse.Adapters.SQL\DataFuse.Adapters.SQL.csproj", "{52986844-698F-486B-AEC9-846AAF50CF46}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.WebAPI", "src\DataFuse.Adapters.WebAPI\DataFuse.Adapters.WebAPI.csproj", "{0C1A05D2-653D-4F88-B397-BA53E0BA7281}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFuse.Adapters.WebAPI.Tests", "tests\DataFuse.Adapters.WebAPI.Tests\DataFuse.Adapters.WebAPI.Tests.csproj", "{D0EE40C1-87EF-413D-A046-DC37D58BC344}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataFuse.Adapters.MongoDB", "src\DataFuse.Adapters.MongoDB\DataFuse.Adapters.MongoDB.csproj", "{035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataFuse.Adapters.MongoDB.Tests", "tests\DataFuse.Adapters.MongoDB.Tests\DataFuse.Adapters.MongoDB.Tests.csproj", "{A2B3C4D5-E6F7-8901-BCDE-F23456789012}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|x64.Build.0 = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|x86.Build.0 = Debug|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|x64.ActiveCfg = Release|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|x64.Build.0 = Release|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|x86.ActiveCfg = Release|Any CPU
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|x86.Build.0 = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|x64.Build.0 = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|x86.Build.0 = Debug|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|x64.ActiveCfg = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|x64.Build.0 = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|x86.ActiveCfg = Release|Any CPU
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|x86.Build.0 = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|x64.Build.0 = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|x86.Build.0 = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|x64.Build.0 = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|x86.Build.0 = Debug|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|x64.ActiveCfg = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|x64.Build.0 = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|x86.ActiveCfg = Release|Any CPU
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|x86.Build.0 = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.Build.0 = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.Build.0 = Debug|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.ActiveCfg = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.Build.0 = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.ActiveCfg = Release|Any CPU
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.Build.0 = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|x64.Build.0 = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|x86.Build.0 = Debug|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|x64.ActiveCfg = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|x64.Build.0 = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|x86.ActiveCfg = Release|Any CPU
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|x86.Build.0 = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|x64.Build.0 = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|x86.Build.0 = Debug|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|Any CPU.Build.0 = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|x64.ActiveCfg = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|x64.Build.0 = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|x86.ActiveCfg = Release|Any CPU
+ {52986844-698F-486B-AEC9-846AAF50CF46}.Release|x86.Build.0 = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|x64.Build.0 = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|x86.Build.0 = Debug|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|x64.ActiveCfg = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|x64.Build.0 = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|x86.ActiveCfg = Release|Any CPU
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|x86.Build.0 = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|x64.Build.0 = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|x86.Build.0 = Debug|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|x64.ActiveCfg = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|x64.Build.0 = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|x86.ActiveCfg = Release|Any CPU
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|x86.Build.0 = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|x64.Build.0 = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Debug|x86.Build.0 = Debug|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|x64.ActiveCfg = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|x64.Build.0 = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|x86.ActiveCfg = Release|Any CPU
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC}.Release|x86.Build.0 = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|x64.Build.0 = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Debug|x86.Build.0 = Debug|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|x64.ActiveCfg = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|x64.Build.0 = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|x86.ActiveCfg = Release|Any CPU
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
+ {1E319404-8EF0-40A1-A9D7-A404A71A98C4} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
+ {39FD806A-D320-43C9-800F-E9D9BCC90623} = {AF995FEF-BB94-48D0-B02B-6671DA73056B}
+ {FE039675-00BE-4DC5-945F-14E7625170D0} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
+ {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {52986844-698F-486B-AEC9-846AAF50CF46} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {0C1A05D2-653D-4F88-B397-BA53E0BA7281} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {D0EE40C1-87EF-413D-A046-DC37D58BC344} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
+ {035680B0-E7C9-4C37-BFA8-4D91E7B67BAC} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
+ {A2B3C4D5-E6F7-8901-BCDE-F23456789012} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C0FF62D6-1374-4939-A546-432862338528}
+ EndGlobalSection
+EndGlobal
diff --git a/GitVersion.yml b/GitVersion.yml
index 280505f..2f85197 100644
--- a/GitVersion.yml
+++ b/GitVersion.yml
@@ -1,4 +1,4 @@
-next-version: 2.0.0
+next-version: 3.0.0
tag-prefix: '[vV]'
mode: ContinuousDeployment
branches:
diff --git a/Images/data-integration-transparent.png b/Images/data-integration-transparent.png
new file mode 100644
index 0000000..5e6aefb
Binary files /dev/null and b/Images/data-integration-transparent.png differ
diff --git a/Images/data-integration.png b/Images/data-integration.png
new file mode 100644
index 0000000..1d1ddb2
Binary files /dev/null and b/Images/data-integration.png differ
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index daf3b65..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2024 Code Shayk
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/LICENSE.md b/LICENSE.md
index daf3b65..0207e1c 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 Code Shayk
+Copyright (c) 2026 Code Shayk
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 4591607..907b1da 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,264 @@
-#
Schemio v2.0
-[](https://github.com/CodeShayk/Schemio/blob/master/LICENSE.md)
-[](https://github.com/CodeShayk/Schemio/actions/workflows/Build-Master.yml)
-[](https://github.com/CodeShayk/Schemio/releases/latest)
-[](https://github.com/CodeShayk/Schemio/actions/workflows/Master-CodeQL.yml)
-[](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)
---
- #### Nuget Packages
-| Package | Latest | Details |
-| --------| --------| --------|
-| Schemio.Core|[](https://badge.fury.io/nu/Schemio.Core) | Provides `core` functionality to configure nested queries and transformers. With ability to map schema paths (XPath/JSONPath) to entity's object graph. `No QueryEngine` provided and requires implementing IQueryEngine to execute IQuery instances. |
-| Schemio.SQL|[](https://badge.fury.io/nu/Schemio.SQL)| Provides schemio with query engine using `Dapper` to execute SQL queries. |
-| Schemio.EntityFramework|[](https://badge.fury.io/nu/Schemio.EntityFramework)| Provides schemio with `Entity Framework` query engine to execute queries using DbContext. |
-| Schemio.API|[](https://badge.fury.io/nu/Schemio.Api)| Provides schemio with `Web Api` query engine to execute apis using HttpClient. |
-
-## Concept
-### What is Schemio?
-`Schemio` is a data aggregation framework using queries that can target different data platforms.
-
-Key benefits:
-- allows fetching `aggregated` data from `heterogeneous` data storages. You could combine queries targetting different data platforms (example. `SQL`, `API`, `Cache`) to return an aggregated data `entity`.
-- allows `selectively` fetching only `parts` of the aggregated data entity. You could retrieve an aggregated data entity with only `sections` of its `object graph` populated with data depending upon the `schema paths` passed with the request.
-
-### When to use Schemio?
-Schemio is perfect fit for many use cases. Few examples that require the service tier to dynamically fetch aggregated data with high performance, availability and scalability are
-> - Aggregated APIs
-> - Data Reporting
-> - Document Generation (with templated data)
-> - Content Management Systems
-> - Many more
-
-## Getting Started?
-### i. Installation
-Install the latest nuget package as appropriate for `Core`, `Web API`, `SQL` using `Dapper` or `EntityFramework` using commands below.
-
-`Scemio.Core` - for installing schemio for `bespoke` implementation of query engine.
+#
DataFuse v3.0.0
+
+### Like GraphQL, but for your heterogeneous backend systems
+
+[](https://github.com/CodeShayk/DataFuse.Net/blob/master/LICENSE.md)
+[](https://github.com/CodeShayk/DataFuse.Net/actions/workflows/Build-Master.yml)
+[](https://github.com/CodeShayk/DataFuse.Net/releases/latest)
+[](https://github.com/CodeShayk/DataFuse.Net/actions/workflows/Master-CodeQL.yml)
+[](https://dotnet.microsoft.com/en-us/download/dotnet/10.0)
+
+**DataFuse** is a declarative framework that aggregates data from SQL databases, REST APIs, and any heterogeneous datsource into unified, strongly-typed objects â replacing hundreds of lines of manual orchestration code with clean, schema-driven configuration.
+
+---
+
+## The Problem
+
+Building a product page? You need inventory from SQL Server, pricing from a REST API, and reviews from MongoDB. That's 50+ lines of manual fetch-assemble code â sequential, tightly coupled, and repeated across your codebase.
+
+```csharp
+// Without DataFuse: manual orchestration everywhere
+var product = await db.QueryFirstAsync("SELECT * FROM Products WHERE Id = @Id", new { Id = productId });
+var pricing = await httpClient.GetFromJsonAsync($"https://pricing-api/products/{productId}");
+var reviews = await httpClient.GetFromJsonAsync($"https://reviews-api/products/{productId}");
+
+product.Price = pricing.Price;
+product.Reviews = reviews.Select(r => new Review { Rating = r.Stars, Comment = r.Text }).ToArray();
```
-NuGet\Install-Package Schemio.Core
+
+## The Solution
+
+```csharp
+// With DataFuse: declare once, use everywhere
+var product = dataProvider.GetData(new ProductRequest { ProductId = 42 });
```
-`Schemio.SQL` - for installing schemio for SQL with `Dapper` engine.
+
+DataFuse automatically executes the SQL query first, then runs pricing and reviews API calls **in parallel**, passes parent results to child queries, and assembles the final typed object.
+
+---
+
+## Quick Start
+
+### 1. Install
+
+```bash
+dotnet add package DataFuse.Integration
+dotnet add package DataFuse.Adapters.SQL # SQL with Dapper
+dotnet add package DataFuse.Adapters.WebAPI # REST APIs
+dotnet add package DataFuse.Adapters.MongoDB # MongoDB
+```
+
+### 2. Define Your Entity
+
+```csharp
+public class Product : IEntity
+{
+ public int ProductId { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public decimal Discount { get; set; }
+ public Review[] Reviews { get; set; }
+}
```
-NuGet\Install-Package Schemio.SQL
+
+### 3. Create Queries
+
+```csharp
+// SQL query â fetches product from database
+public class ProductQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (ProductRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ "SELECT ProductId as Id, Name, Price FROM Products WHERE ProductId = @Id",
+ new { Id = request.ProductId });
+ }
+}
+
+// MongoDB query â fetches reviews from MongoDB, receives parent result
+public class ReviewsMongoQuery : MongoQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult;
+ return async database =>
+ {
+ var collection = database.GetCollection("reviews");
+ var reviews = await collection.Find(r => r.ProductId == product.Id).ToListAsync();
+ return new CollectionResult(reviews);
+ };
+ }
+}
+
+// API query â fetches live pricing from external service, receives parent result
+public class PricingApiQuery : WebQuery
+{
+ public PricingApiQuery() : base("https://api.pricing.com/") { }
+
+ protected override Func GetQuery(IDataContext context, IQueryResult parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult;
+ return () => new Uri($"products/{product.Id}/pricing", UriKind.Relative);
+ }
+}
```
-`Schemio.EntityFramework` - for installing schemio for SQL with `EntityFramework` engine.
+
+### 4. Create Transformers
+
+```csharp
+public class ProductTransform : BaseTransformer
+{
+ public override void Transform(ProductResult queryResult, Product entity)
+ {
+ entity.ProductId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ entity.Price = queryResult.Price;
+ }
+}
+
+public class PricingTransform : BaseTransformer
+{
+ public override void Transform(PricingResult queryResult, Product entity)
+ {
+ entity.Price = queryResult.CurrentPrice;
+ entity.Discount = queryResult.DiscountPercent;
+ }
+}
+
+public class ReviewsTransform : BaseTransformer, Product>
+{
+ public override void Transform(CollectionResult queryResult, Product entity)
+ {
+ entity.Reviews = queryResult?.Select(r => new Review
+ {
+ ReviewId = r.Id, Comment = r.Comment, Rating = r.Rating
+ }).ToArray() ?? Array.Empty();
+ }
+}
```
-NuGet\Install-Package Schemio.EntityFramework
+
+### 5. Configure the Schema
+
+```csharp
+public class ProductConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("product"),
+ product => product.Dependents
+ .Map(For.Paths("product/pricing"))
+ .Map(For.Paths("product/reviews")))
+ .End();
+ }
+}
```
-`Schemio.API` - for installing schemio for Web API with `HttpClient` engine.
+
+### 6. Register & Use
+
+```csharp
+// DI registration
+services.UseDataFuse()
+ .WithEngine(c => new QueryEngine(sqlConfiguration)) // SQL
+ .WithEngine() // REST API
+ .WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase)) // MongoDB
+ .WithPathMatcher(c => new XPathMatcher())
+ .WithEntityConfiguration(c => new ProductConfiguration());
+
+services.AddHttpClient();
```
-NuGet\Install-Package Schemio.API
+
+```csharp
+// Usage â one line to get fully hydrated data
+public class ProductService
+{
+ private readonly IDataProvider _dataProvider;
+
+ public ProductService(IDataProvider dataProvider) => _dataProvider = dataProvider;
+
+ public Product GetProduct(int productId)
+ => _dataProvider.GetData(new ProductRequest { ProductId = productId });
+
+ // Selective loading â only fetch product + reviews, skip other paths
+ public Product GetProductWithReviews(int productId)
+ => _dataProvider.GetData(new ProductRequest
+ {
+ ProductId = productId,
+ SchemaPaths = new[] { "product", "product/reviews" }
+ });
+}
```
-### ii. Developer Guide
-Please see [Developer Guide](https://codeshayk.github.io/Schemio/) for details on how to implement schemio in your project.
+---
+
+## Key Features
+
+| Feature | Description |
+|---|---|
+| **Declarative Schema** | Define data relationships once with fluent configuration |
+| **Automatic Parallelism** | Sibling queries run in parallel â no `Task.WhenAll` boilerplate |
+| **Selective Loading** | Fetch only the data paths the consumer needs via `SchemaPaths` |
+| **Parent-Child Dependencies** | Parent results flow to child queries automatically |
+| **Cross-Source Mixing** | Combine SQL + REST API + MongoDB + EF Core queries in one entity |
+| **Type Safety** | Strongly-typed queries, results, and transformers |
+| **Built-in Caching** | `[CacheResult]` attribute for expensive query results |
+| **Custom Adapters** | Add any data source by implementing `IQueryEngine` |
+
+---
+
+## Packages
+
+| Package | Purpose | Install |
+|---|---|---|
+| **DataFuse.Integration** | Core orchestration, DI, helpers | `dotnet add package DataFuse.Integration` |
+| **DataFuse.Adapters.SQL** | SQL via Dapper | `dotnet add package DataFuse.Adapters.SQL` |
+| **DataFuse.Adapters.EntityFramework** | EF Core | `dotnet add package DataFuse.Adapters.EntityFramework` |
+| **DataFuse.Adapters.WebAPI** | REST APIs via HttpClient | `dotnet add package DataFuse.Adapters.WebAPI` |
+| **DataFuse.Adapters.MongoDB** | MongoDB via official driver | `dotnet add package DataFuse.Adapters.MongoDB` |
+| **DataFuse.Adapters.Abstraction** | Interfaces & base classes | Included as dependency |
+
+### Compatibility
+
+| Package | .NET | .NET Standard | .NET Framework |
+|---|---|---|---|
+| DataFuse.Integration | 8.0, 9.0, 10.0 | 2.1 | - |
+| DataFuse.Adapters.Abstraction | 8.0, 9.0, 10.0 | 2.1 | - |
+| DataFuse.Adapters.SQL | 8.0, 9.0, 10.0 | 2.1 | - |
+| DataFuse.Adapters.WebAPI | 8.0, 9.0, 10.0 | 2.1 | - |
+| DataFuse.Adapters.MongoDB | 8.0, 9.0, 10.0 | 2.1 | - |
+| DataFuse.Adapters.EntityFramework | 10.0 | - | - |
+
+---
+
+## Documentation
+
+See the [Complete Developer Guide](https://codeshayk.github.io/DataFuse.Net/) for detailed documentation including:
+- Real-world use cases (e-commerce, customer 360, reporting)
+- Core concepts deep dive
+- Query implementation guides (SQL, EF Core, Web API, MongoDB)
+- Transformer patterns
+- Advanced features (caching, selective loading, custom engines)
+- Architecture overview
+
+---
## Support
-If you are having problems, please let me know by [raising a new issue](https://github.com/CodeShayk/Schemio/issues/new/choose).
+If you are having problems, please let us know by [raising a new issue](https://github.com/CodeShayk/DataFuse.Net/issues/new/choose).
## License
This project is licensed with the [MIT license](LICENSE).
## Version History
-The main branch is now on .NET 8.0. The following previous versions are available:
-| Version | Release Notes | Developer Guide |
-| -------- | --------|--------|
-| [`v1.0.0`](https://github.com/CodeShayk/Schemio/tree/v1.0.0) | [Notes](https://github.com/CodeShayk/Schemio/releases/tag/v1.0.0) | [Guide](https://github.com/CodeShayk/Schemio/blob/v1.0.0/index.md) |
-| [`Pre-Release v2.0.0`](https://github.com/CodeShayk/Schemio/tree/v2.0.0) | [Notes](https://github.com/CodeShayk/Schemio/releases/tag/v2.0.0) | [Guide](https://github.com/CodeShayk/Schemio/blob/v2.0.0/index.md) |
-
-## Credits
-Thank you for reading. Please fork, explore, contribute and report. Happy Coding !! :)
-
-
+The main branch is now on .NET 10.0. Previous versions:
+| Version | Release Notes | Developer Guide |
+|---|---|---|
+| [`v3.0.0`](https://github.com/CodeShayk/DataFuse.Net/tree/v3.0.0) | [Notes](https://github.com/CodeShayk/DataFuse.Net/releases/tag/v3.0.0) | [Guide](https://github.com/CodeShayk/DataFuse.Net/blob/v3.0.0/index.md) |
+| [`v2.0.0`](https://github.com/CodeShayk/DataFuse.Net/tree/v2.0.0) | [Notes](https://github.com/CodeShayk/DataFuse.Net/releases/tag/v2.0.0) | [Guide](https://github.com/CodeShayk/DataFuse.Net/blob/v2.0.0/index.md) |
+| [`v1.0.0`](https://github.com/CodeShayk/DataFuse.Net/tree/v1.0.0) | [Notes](https://github.com/CodeShayk/DataFuse.Net/releases/tag/v1.0.0) | [Guide](https://github.com/CodeShayk/DataFuse.Net/blob/v1.0.0/index.md) |
diff --git a/Schemio.sln b/Schemio.sln
deleted file mode 100644
index 75e0047..0000000
--- a/Schemio.sln
+++ /dev/null
@@ -1,99 +0,0 @@
-īģŋ
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.5.33516.290
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F41DA3D8-A0E9-4A05-8A35-78313C0F5804}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{AF995FEF-BB94-48D0-B02B-6671DA73056B}"
- ProjectSection(SolutionItems) = preProject
- .gitignore = .gitignore
- index.md = index.md
- LICENSE.md = LICENSE.md
- README.md = README.md
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.Core.Tests", "tests\Schemio.Core.Tests\Schemio.Core.Tests.csproj", "{B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.SQL.Tests", "tests\Schemio.SQL.Tests\Schemio.SQL.Tests.csproj", "{1E319404-8EF0-40A1-A9D7-A404A71A98C4}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{39FD806A-D320-43C9-800F-E9D9BCC90623}"
- ProjectSection(SolutionItems) = preProject
- .github\workflows\Build-Master.yml = .github\workflows\Build-Master.yml
- GitVersion.yml = GitVersion.yml
- .github\workflows\Master-CodeQL.yml = .github\workflows\Master-CodeQL.yml
- .github\workflows\PullRequest-CI.yml = .github\workflows\PullRequest-CI.yml
- .github\workflows\PullRequest-CodeQL.yml = .github\workflows\PullRequest-CodeQL.yml
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.EntityFramework.Tests", "tests\Schemio.EntityFramework.Tests\Schemio.EntityFramework.Tests.csproj", "{FE039675-00BE-4DC5-945F-14E7625170D0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.Core", "src\Schemio.Core\Schemio.Core.csproj", "{4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.EntityFramework", "src\Schemio.EntityFramework\Schemio.EntityFramework.csproj", "{E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.SQL", "src\Schemio.SQL\Schemio.SQL.csproj", "{52986844-698F-486B-AEC9-846AAF50CF46}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.API", "src\Schemio.API\Schemio.API.csproj", "{0C1A05D2-653D-4F88-B397-BA53E0BA7281}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schemio.API.Tests", "tests\Schemio.API.Tests\Schemio.API.Tests.csproj", "{D0EE40C1-87EF-413D-A046-DC37D58BC344}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB}.Release|Any CPU.Build.0 = Release|Any CPU
- {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1E319404-8EF0-40A1-A9D7-A404A71A98C4}.Release|Any CPU.Build.0 = Release|Any CPU
- {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FE039675-00BE-4DC5-945F-14E7625170D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FE039675-00BE-4DC5-945F-14E7625170D0}.Release|Any CPU.Build.0 = Release|Any CPU
- {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C}.Release|Any CPU.Build.0 = Release|Any CPU
- {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB}.Release|Any CPU.Build.0 = Release|Any CPU
- {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {52986844-698F-486B-AEC9-846AAF50CF46}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {52986844-698F-486B-AEC9-846AAF50CF46}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {52986844-698F-486B-AEC9-846AAF50CF46}.Release|Any CPU.Build.0 = Release|Any CPU
- {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0C1A05D2-653D-4F88-B397-BA53E0BA7281}.Release|Any CPU.Build.0 = Release|Any CPU
- {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D0EE40C1-87EF-413D-A046-DC37D58BC344}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {B09236CB-BBD2-4DCF-A698-74CCCAB29FFB} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
- {1E319404-8EF0-40A1-A9D7-A404A71A98C4} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
- {39FD806A-D320-43C9-800F-E9D9BCC90623} = {AF995FEF-BB94-48D0-B02B-6671DA73056B}
- {FE039675-00BE-4DC5-945F-14E7625170D0} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
- {4F9B6FE3-CAC4-4594-84AD-98D1ECDE180C} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
- {E8F8C13E-2E05-4092-84FD-B7B7B12DABBB} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
- {52986844-698F-486B-AEC9-846AAF50CF46} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
- {0C1A05D2-653D-4F88-B397-BA53E0BA7281} = {F41DA3D8-A0E9-4A05-8A35-78313C0F5804}
- {D0EE40C1-87EF-413D-A046-DC37D58BC344} = {07BAE427-96CF-4F9B-80A9-48CFB0A89CF3}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {C0FF62D6-1374-4939-A546-432862338528}
- EndGlobalSection
-EndGlobal
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..3028a60
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,1128 @@
+# DataFuse Framework
+
+### Like GraphQL, but for your heterogeneous backend systems
+
+**DataFuse** is a declarative .NET framework that aggregates data from SQL databases, REST APIs, MongoDB, and Entity Framework into unified, strongly-typed objects â replacing hundreds of lines of manual orchestration code with a clean, schema-driven configuration.
+
+[](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)
+[](https://github.com/CodeShayk/DataFuse.Net/blob/master/LICENSE.md)
+[](https://github.com/CodeShayk/DataFuse.Net/releases/latest)
+
+---
+
+## Table of Contents
+
+1. [Real-World Use Cases](#real-world-use-cases)
+2. [Why DataFuse?](#why-datafuse)
+3. [Quick Start (5 Minutes)](#quick-start)
+4. [Core Concepts](#core-concepts)
+5. [Packages](#packages)
+6. [Query Implementation Guide](#query-implementation-guide)
+7. [Transformer Guide](#transformer-guide)
+8. [Advanced Features](#advanced-features)
+9. [Architecture](#architecture)
+10. [Best Practices](#best-practices)
+11. [Getting Support](#getting-support)
+
+---
+
+## Real-World Use Cases
+
+### 1. E-Commerce Product Page
+
+Your product page needs data from **three different systems**: inventory from a SQL Server database, live pricing from a pricing microservice REST API, and customer reviews from MongoDB.
+
+**Without DataFuse** â you write this every time:
+
+```csharp
+// 50+ lines of manual orchestration, repeated across your codebase
+public async Task GetProductPage(int productId)
+{
+ var product = await _db.QueryFirstAsync(
+ "SELECT * FROM Products WHERE Id = @Id", new { Id = productId });
+
+ var pricing = await _httpClient.GetFromJsonAsync(
+ $"https://pricing-api/products/{productId}");
+
+ var reviews = await _mongoDb.GetCollection("reviews")
+ .Find(r => r.ProductId == productId).ToListAsync();
+
+ // Manual assembly â error-prone, no caching, no parallel execution
+ return new ProductPage
+ {
+ ProductId = product.Id,
+ Name = product.Name,
+ Description = product.Description,
+ CurrentPrice = pricing.Price,
+ DiscountPercent = pricing.Discount,
+ Reviews = reviews.Select(r => new Review
+ {
+ Rating = r.Stars,
+ Comment = r.Text,
+ Author = r.AuthorName
+ }).ToArray(),
+ AverageRating = reviews.Average(r => r.Stars)
+ };
+}
+```
+
+**With DataFuse** â declare your schema once, use everywhere:
+
+```csharp
+public class ProductPageConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("product"),
+ product => product.Dependents
+ .Map(For.Paths("product/pricing"))
+ .Map(For.Paths("product/reviews")))
+ .End();
+ }
+}
+
+// Usage â one line to get fully hydrated data
+var productPage = dataProvider.GetData(new ProductRequest { ProductId = 42 });
+```
+
+DataFuse automatically:
+- Executes the SQL product query first
+- Runs pricing and reviews API calls **in parallel** (they're siblings)
+- Passes the product result to dependent queries so they know which product to fetch
+- Assembles the final `ProductPage` object via type-safe transformers
+
+### 2. Customer 360 Dashboard
+
+Build a unified customer view pulling from a CRM database, a billing REST API, and a support ticket system:
+
+```csharp
+public class Customer360Configuration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ customer => customer.Dependents
+ .Map(For.Paths("customer/billing"))
+ .Map(For.Paths("customer/tickets"))
+ .Map(For.Paths("customer/orders"),
+ orders => orders.Dependents
+ .Map(
+ For.Paths("customer/orders/order/items"))))
+ .End();
+ }
+}
+```
+
+Need just the basic profile without orders? Use **selective loading**:
+
+```csharp
+var basicProfile = dataProvider.GetData(new CustomerRequest
+{
+ CustomerId = 123,
+ SchemaPaths = new[] { "customer", "customer/billing" }
+});
+```
+
+### 3. Multi-Service Reporting
+
+Aggregate metrics from multiple microservices into a single report object, mixing SQL databases with REST APIs:
+
+```csharp
+public class SalesReportConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("report"),
+ report => report.Dependents
+ .Map(For.Paths("report/inventory"))
+ .Map(For.Paths("report/shipping"))
+ .Map(For.Paths("report/revenue")))
+ .End();
+ }
+}
+```
+
+---
+
+## Why DataFuse?
+
+### The Problem
+
+In modern architectures, a single page or API response often needs data from **multiple backend systems** â SQL databases, REST APIs, MongoDB, third-party services, caches. The standard approach is to write manual orchestration code for each scenario. This leads to:
+
+- **Boilerplate explosion**: Every new data combination means another 50+ lines of fetch-assemble-transform code
+- **No parallelism by default**: Developers write sequential calls unless they manually add `Task.WhenAll`
+- **Tight coupling**: Changing a data source means rewriting orchestration code
+- **No selective loading**: You fetch everything even when the consumer only needs a subset
+- **Inconsistent patterns**: Every developer solves the same problem differently
+
+### How DataFuse Solves This
+
+DataFuse provides a **declarative, schema-driven approach** where you:
+
+1. **Define** your entity (the shape of the data you want)
+2. **Configure** a schema mapping queries to entity paths
+3. **Let DataFuse handle** execution order, parallelism, dependency passing, and assembly
+
+### DataFuse vs Alternatives
+
+| Capability | Manual Code | GraphQL | MediatR | **DataFuse** |
+|---|---|---|---|---|
+| Multi-source aggregation | Manual wiring | Resolver-based | Manual wiring | **Declarative schema** |
+| Parallel execution | Manual `Task.WhenAll` | Per-resolver | Manual | **Automatic** |
+| Selective loading | Manual if/else | Built-in | Manual | **Schema path filtering** |
+| Dependency management | Manual ordering | Implicit | Manual | **Parent-child hierarchy** |
+| Type safety | Varies | Schema-based | Yes | **Strongly typed** |
+| New data source support | Rewrite orchestration | New resolver | New handler | **Add adapter (SQL, API, MongoDB, EF, custom)** |
+| Learning curve | None | High (new language) | Low | **Low (C# only)** |
+| Backend-only (no client changes) | Yes | No (client queries) | Yes | **Yes** |
+
+### When to Use DataFuse
+
+**Use DataFuse when:**
+- Your data lives across **different systems** (SQL + APIs + external services)
+- You need to **compose complex object graphs** from multiple sources
+- You want **automatic parallelism** without managing it yourself
+- You need **selective loading** â different consumers need different subsets of data
+- You're building **API gateways**, **BFF patterns**, or **composite APIs**
+
+**Use plain Dapper/EF Core when:**
+- All your data is in a single database
+- Simple queries with SQL joins suffice
+
+**Use GraphQL when:**
+- You need client-controlled query shapes
+- You're building a public API where consumers define what they need
+
+---
+
+## Quick Start
+
+Get up and running in 5 minutes.
+
+### 1. Install Packages
+
+```bash
+dotnet add package DataFuse.Integration
+dotnet add package DataFuse.Adapters.SQL # For SQL with Dapper
+dotnet add package DataFuse.Adapters.WebAPI # For REST APIs
+dotnet add package DataFuse.Adapters.MongoDB # For MongoDB
+dotnet add package DataFuse.Adapters.EntityFramework # For EF Core
+```
+
+### 2. Define Your Entity
+
+```csharp
+public class Product : IEntity
+{
+ public int ProductId { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public Category Category { get; set; }
+ public Review[] Reviews { get; set; }
+}
+```
+
+### 3. Create Queries
+
+**SQL query** (fetches product from database):
+```csharp
+public class ProductQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (ProductRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ "SELECT ProductId as Id, Name, Price, CategoryId FROM Products WHERE ProductId = @Id",
+ new { Id = request.ProductId });
+ }
+}
+```
+
+**MongoDB query** (fetches reviews from MongoDB):
+```csharp
+public class ReviewsMongoQuery : MongoQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult; // Parent result is available
+ return async database =>
+ {
+ var collection = database.GetCollection("reviews");
+ var reviews = await collection.Find(r => r.ProductId == product.Id).ToListAsync();
+ return new CollectionResult(reviews);
+ };
+ }
+}
+```
+
+### 4. Create Transformers
+
+```csharp
+public class ProductTransform : BaseTransformer
+{
+ public override void Transform(ProductResult queryResult, Product entity)
+ {
+ entity.ProductId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ entity.Price = queryResult.Price;
+ }
+}
+
+public class ReviewsTransform : BaseTransformer, Product>
+{
+ public override void Transform(CollectionResult queryResult, Product entity)
+ {
+ entity.Reviews = queryResult?.Select(r => new Review
+ {
+ ReviewId = r.Id, Comment = r.Comment, Rating = r.Rating
+ }).ToArray() ?? Array.Empty();
+ }
+}
+```
+
+### 5. Configure the Schema
+
+```csharp
+public class ProductConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("product"),
+ product => product.Dependents
+ .Map(For.Paths("product/category"))
+ .Map(For.Paths("product/reviews")))
+ .End();
+ }
+}
+```
+
+### 6. Register with DI
+
+```csharp
+services.UseDataFuse()
+ .WithEngine(c => new QueryEngine(sqlConfiguration)) // SQL adapter
+ .WithEngine() // Web API adapter
+ .WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase)) // MongoDB adapter
+ .WithPathMatcher(c => new XPathMatcher())
+ .WithEntityConfiguration(c => new ProductConfiguration());
+
+services.AddHttpClient();
+```
+
+### 7. Use It
+
+```csharp
+public class ProductService
+{
+ private readonly IDataProvider _dataProvider;
+
+ public ProductService(IDataProvider dataProvider)
+ {
+ _dataProvider = dataProvider;
+ }
+
+ public Product GetProduct(int productId)
+ {
+ return _dataProvider.GetData(new ProductRequest { ProductId = productId });
+ }
+
+ // Selective loading â only fetch product + reviews, skip category
+ public Product GetProductWithReviews(int productId)
+ {
+ return _dataProvider.GetData(new ProductRequest
+ {
+ ProductId = productId,
+ SchemaPaths = new[] { "product", "product/reviews" }
+ });
+ }
+}
+```
+
+---
+
+## Core Concepts
+
+### Entities
+
+Entities represent the final aggregated data structure. They implement `IEntity` and define the complete object graph that DataFuse will hydrate from multiple sources:
+
+```csharp
+public class Customer : IEntity
+{
+ public int CustomerId { get; set; }
+ public string Name { get; set; }
+
+ // Each of these can come from a different data source
+ public Communication Communication { get; set; } // From REST API
+ public Address Address { get; set; } // From SQL database
+ public Order[] Orders { get; set; } // From EF Core
+}
+```
+
+### Queries
+
+Queries fetch data from a specific source. DataFuse provides base classes for common sources:
+
+| Base Class | Source | Adapter Package |
+|---|---|---|
+| `SQLQuery` | SQL databases via Dapper | `DataFuse.Adapters.SQL` |
+| `SQLQuery` (EF) | Entity Framework Core | `DataFuse.Adapters.EntityFramework` |
+| `MongoQuery` | MongoDB collections | `DataFuse.Adapters.MongoDB` |
+| `WebQuery` | REST APIs via HttpClient | `DataFuse.Adapters.WebAPI` |
+
+#### Parent-Child Query Dependencies
+
+Child queries receive their parent's result, enabling dependent data fetching:
+
+```csharp
+// Root query â fetches customer from database
+public class CustomerQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ "SELECT CustomerId as Id, Name, Code FROM Customers WHERE CustomerId = @Id",
+ new { Id = request.CustomerId });
+ }
+}
+
+// Child query â uses parent's CustomerId to fetch orders
+public class OrdersQuery : SQLQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+ return async connection =>
+ {
+ var orders = await connection.QueryAsync(
+ "SELECT OrderId, OrderNumber, OrderDate FROM Orders WHERE CustomerId = @Id",
+ new { Id = customer.Id });
+ return new CollectionResult(orders);
+ };
+ }
+}
+```
+
+#### Execution Order
+
+```
+1. Root Query (CustomerQuery) executes first
+ |
+ v CustomerResult passed to children
+
+2. Child Queries execute IN PARALLEL:
+ - OrdersQuery (uses CustomerId)
+ - CommunicationQuery (uses CustomerId)
+ - AddressQuery (uses CustomerId)
+ |
+ v OrderResult passed to grandchildren
+
+3. Grandchild Queries execute:
+ - OrderItemsQuery (uses OrderId from OrderResult)
+```
+
+Queries at the same level run in parallel automatically. DataFuse manages the dependency tree.
+
+### Transformers
+
+Transformers map query results onto the entity. Each query has a paired transformer:
+
+```csharp
+public class CustomerTransform : BaseTransformer
+{
+ public override void Transform(CustomerResult queryResult, Customer entity)
+ {
+ entity.CustomerId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ }
+}
+
+public class OrdersTransform : BaseTransformer, Customer>
+{
+ public override void Transform(CollectionResult queryResult, Customer entity)
+ {
+ entity.Orders = queryResult?.Select(o => new Order
+ {
+ OrderId = o.OrderId,
+ OrderNumber = o.OrderNumber,
+ OrderDate = o.OrderDate
+ }).ToArray() ?? Array.Empty();
+ }
+}
+```
+
+### Schema Configuration
+
+The schema defines the full query-transform-path hierarchy:
+
+```csharp
+public class CustomerConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ customer => customer.Dependents
+ .Map(
+ For.Paths("customer/communication"))
+ .Map(For.Paths("customer/orders"),
+ orders => orders.Dependents
+ .Map(
+ For.Paths("customer/orders/order/items"))))
+ .End();
+ }
+}
+```
+
+Schema paths correspond to the entity's object graph:
+- `customer` â root properties
+- `customer/communication` â Customer.Communication
+- `customer/orders` â Customer.Orders collection
+- `customer/orders/order/items` â Order.Items for each order
+
+---
+
+## Packages
+
+### DataFuse.Integration
+
+Core package with orchestration, DI extensions, helpers, and path matchers.
+
+```bash
+dotnet add package DataFuse.Integration
+```
+
+**Key components:** `DataProvider`, `QueryBuilder`, `EntityBuilder`, `DataFuseOptionsBuilder`, XPath/JSONPath matchers, DI registration via `UseDataFuse()`.
+
+### DataFuse.Adapters.Abstraction
+
+Interfaces and base classes: `IEntity`, `IQuery`, `IQueryResult`, `ITransformer`, `IQueryEngine`, `BaseQuery`, `BaseTransformer`, `EntityConfiguration`, `CreateSchema`, `CollectionResult`, `CacheResultAttribute`.
+
+### DataFuse.Adapters.SQL
+
+SQL database support using Dapper.
+
+```bash
+dotnet add package DataFuse.Adapters.SQL
+```
+
+Supports SQL Server, SQLite, MySQL, PostgreSQL, Oracle.
+
+### DataFuse.Adapters.EntityFramework
+
+Entity Framework Core integration.
+
+```bash
+dotnet add package DataFuse.Adapters.EntityFramework
+```
+
+Full LINQ support, DbContext factory integration.
+
+### DataFuse.Adapters.MongoDB
+
+MongoDB support using the official MongoDB driver.
+
+```bash
+dotnet add package DataFuse.Adapters.MongoDB
+```
+
+Full `IMongoDatabase` access, LINQ and filter builder support.
+
+### DataFuse.Adapters.WebAPI
+
+REST API support using HttpClient.
+
+```bash
+dotnet add package DataFuse.Adapters.WebAPI
+```
+
+Request/response header management, JSON deserialization.
+
+### Compatibility
+
+| Package | .NET Framework | .NET Standard | .NET |
+|---|---|---|---|
+| DataFuse.Integration | 4.6.2+ | 2.0, 2.1 | 9.0+ |
+| DataFuse.Adapters.SQL | 4.6.2+ | 2.1 | 9.0+ |
+| DataFuse.Adapters.EntityFramework | - | - | 9.0+ |
+| DataFuse.Adapters.MongoDB | - | - | 9.0+ |
+| DataFuse.Adapters.WebAPI | 4.6.2+ | 2.0, 2.1 | 9.0+ |
+
+---
+
+## Query Implementation Guide
+
+### SQL Queries (Dapper)
+
+```csharp
+// Single result
+public class CustomerQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ @"SELECT CustomerId as Id, CustomerName as Name, CustomerCode as Code
+ FROM Customers WHERE CustomerId = @CustomerId",
+ new { CustomerId = request.CustomerId });
+ }
+}
+
+// Collection result
+public class OrdersQuery : SQLQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+ return async connection =>
+ {
+ var orders = await connection.QueryAsync(
+ "SELECT OrderId, OrderNumber, OrderDate FROM Orders WHERE CustomerId = @Id",
+ new { Id = customer.Id });
+ return new CollectionResult(orders);
+ };
+ }
+}
+```
+
+### Entity Framework Queries
+
+```csharp
+public class CustomerQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return async dbContext =>
+ {
+ return await dbContext.Set()
+ .Where(c => c.CustomerId == request.CustomerId)
+ .Select(c => new CustomerResult
+ {
+ Id = c.CustomerId,
+ Name = c.Name,
+ Code = c.Code
+ })
+ .FirstOrDefaultAsync();
+ };
+ }
+}
+```
+
+### MongoDB Queries
+
+```csharp
+// Single document
+public class CustomerQuery : MongoQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return async database =>
+ {
+ var collection = database.GetCollection("customers");
+ return await collection.Find(c => c.Id == request.CustomerId).FirstOrDefaultAsync();
+ };
+ }
+}
+
+// Collection query with filter
+public class OrdersQuery : MongoQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+ return async database =>
+ {
+ var collection = database.GetCollection("orders");
+ var filter = Builders.Filter.Eq(o => o.CustomerId, customer.Id);
+ var orders = await collection.Find(filter).SortByDescending(o => o.OrderDate).ToListAsync();
+ return new CollectionResult(orders);
+ };
+ }
+}
+
+// Aggregation pipeline
+public class SalesSummaryQuery : MongoQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+ return async database =>
+ {
+ var collection = database.GetCollection("orders");
+ var result = await collection.Aggregate()
+ .Match(Builders.Filter.Eq("customerId", customer.Id))
+ .Group(new BsonDocument
+ {
+ { "_id", "$customerId" },
+ { "totalSpent", new BsonDocument("$sum", "$amount") },
+ { "orderCount", new BsonDocument("$sum", 1) }
+ })
+ .FirstOrDefaultAsync();
+
+ return new SalesSummaryResult
+ {
+ TotalSpent = result?["totalSpent"].ToDecimal() ?? 0,
+ OrderCount = result?["orderCount"].ToInt32() ?? 0
+ };
+ };
+ }
+}
+```
+
+### Web API Queries
+
+```csharp
+// Basic API query
+public class PricingApiQuery : WebQuery
+{
+ public PricingApiQuery() : base("https://api.pricing.com/") { }
+
+ protected override Func GetQuery(IDataContext context, IQueryResult parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult;
+ return () => new Uri($"products/{product.Id}/pricing", UriKind.Relative);
+ }
+}
+
+// API query with custom headers
+public class AuthenticatedApiQuery : WebQuery
+{
+ public AuthenticatedApiQuery() : base("https://api.secure.com/") { }
+
+ protected override Func GetQuery(IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (SecureRequest)context.Request;
+ return () => new Uri($"secure/data/{request.Id}", UriKind.Relative);
+ }
+
+ protected override IDictionary GetRequestHeaders()
+ {
+ return new Dictionary
+ {
+ { "Authorization", "Bearer " + GetAccessToken() },
+ { "Accept", "application/json" }
+ };
+ }
+
+ protected override IEnumerable GetResponseHeaders()
+ {
+ return new[] { "X-Rate-Limit-Remaining", "X-Request-Id" };
+ }
+}
+```
+
+### Query Result Types
+
+```csharp
+// Simple result
+public class CustomerResult : IQueryResult
+{
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Code { get; set; }
+}
+
+// Collection result
+public class CollectionResult : List, IQueryResult
+{
+ public CollectionResult(IEnumerable items) : base(items) { }
+ public CollectionResult() { }
+}
+
+// Cached result â cached automatically across queries
+[CacheResult]
+public class CategoryResult : IQueryResult
+{
+ public int Id { get; set; }
+ public string Name { get; set; }
+}
+
+// Web result with response headers
+public class UserApiResult : WebHeaderResult
+{
+ public int Id { get; set; }
+ public string Name { get; set; }
+}
+```
+
+---
+
+## Transformer Guide
+
+### Basic Transformers
+
+```csharp
+public class CustomerTransform : BaseTransformer
+{
+ public override void Transform(CustomerResult queryResult, Customer entity)
+ {
+ if (queryResult == null) return;
+
+ entity.CustomerId = queryResult.Id;
+ entity.CustomerName = queryResult.Name ?? string.Empty;
+ entity.CustomerCode = queryResult.Code;
+ }
+}
+```
+
+### Collection Transformers
+
+```csharp
+public class OrdersTransform : BaseTransformer, Customer>
+{
+ public override void Transform(CollectionResult queryResult, Customer entity)
+ {
+ entity.Orders = queryResult?.Select(o => new Order
+ {
+ OrderId = o.OrderId,
+ OrderNumber = o.OrderNumber,
+ OrderDate = o.OrderDate,
+ TotalAmount = o.TotalAmount
+ }).ToArray() ?? Array.Empty();
+ }
+}
+```
+
+### Context-Aware Transformers
+
+Transformers can access the request context for conditional logic:
+
+```csharp
+public class ProductTransform : BaseTransformer
+{
+ public override void Transform(ProductResult queryResult, Product entity)
+ {
+ entity.ProductId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ entity.Price = queryResult.Price;
+
+ var request = Context.Request as ProductRequest;
+ if (request?.IncludeMetadata == true)
+ {
+ entity.CreatedDate = queryResult.CreatedDate;
+ entity.LastModified = queryResult.LastModified;
+ }
+ }
+}
+```
+
+### Grandchild Transformers
+
+For deeply nested data, transformers map grandchild results back to the correct parent:
+
+```csharp
+public class OrderItemsTransform : BaseTransformer, Customer>
+{
+ public override void Transform(CollectionResult queryResult, Customer entity)
+ {
+ if (queryResult == null || !queryResult.Any()) return;
+
+ var itemsByOrder = queryResult.GroupBy(item => item.OrderId);
+ foreach (var group in itemsByOrder)
+ {
+ var order = entity.Orders.FirstOrDefault(o => o.OrderId == group.Key);
+ if (order != null)
+ {
+ order.Items = group.Select(item => new OrderItem
+ {
+ ItemId = item.ItemId,
+ ProductName = item.ProductName,
+ Quantity = item.Quantity,
+ Price = item.Price
+ }).ToArray();
+ }
+ }
+ }
+}
+```
+
+---
+
+## Advanced Features
+
+### Caching
+
+Mark query results with `[CacheResult]` to cache them for use in other queries and transformers:
+
+```csharp
+[CacheResult]
+public class CategoryResult : IQueryResult
+{
+ public int Id { get; set; }
+ public string Name { get; set; }
+}
+
+// Access cached results in a transformer
+public class ProductTransform : BaseTransformer
+{
+ public override void Transform(ProductResult queryResult, Product entity)
+ {
+ entity.ProductId = queryResult.Id;
+
+ if (Context.Cache.TryGetValue("CategoryResult", out var cached))
+ {
+ entity.CategoryName = ((CategoryResult)cached).Name;
+ }
+ }
+}
+```
+
+Caching is useful when a grandchild query needs data from a grandparent query that isn't its direct parent.
+
+### Selective Loading
+
+Control which parts of the object graph to load via `SchemaPaths`:
+
+```csharp
+// Load everything
+var fullCustomer = dataProvider.GetData(new CustomerRequest
+{
+ CustomerId = 123
+ // SchemaPaths = null loads all configured paths
+});
+
+// Load only customer + orders (skip communication, address, etc.)
+var withOrders = dataProvider.GetData(new CustomerRequest
+{
+ CustomerId = 123,
+ SchemaPaths = new[] { "customer", "customer/orders" }
+});
+
+// Load just the basic profile
+var basicProfile = dataProvider.GetData(new CustomerRequest
+{
+ CustomerId = 123,
+ SchemaPaths = new[] { "customer" }
+});
+```
+
+This avoids unnecessary queries â if a consumer only needs the customer name, DataFuse won't execute order or communication queries.
+
+### Parallel Execution
+
+Sibling queries at the same level execute in parallel automatically:
+
+```csharp
+return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ customer => customer.Dependents
+ .Map(For.Paths("customer/contact")) // Parallel
+ .Map(For.Paths("customer/preferences")) // Parallel
+ .Map(For.Paths("customer/address"))) // Parallel
+ .End();
+```
+
+No `Task.WhenAll` boilerplate needed. DataFuse manages execution order based on the dependency tree.
+
+### Conditional Query Execution
+
+Child queries can skip execution based on parent data:
+
+```csharp
+public class PremiumServicesQuery : WebQuery
+{
+ protected override Func GetQuery(IDataContext context, IQueryResult parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+
+ if (customer.CustomerType != "Premium")
+ return null; // Returning null skips this query
+
+ return () => new Uri($"premium-services/{customer.Id}", UriKind.Relative);
+ }
+}
+```
+
+### Cross-Source Dependencies
+
+Mix data sources within the same entity. A root query can be SQL while its children pull from MongoDB and REST APIs:
+
+```csharp
+return CreateSchema.For()
+ .Map(For.Paths("customer"), // SQL
+ customer => customer.Dependents
+ .Map(For.Paths("customer/billing")) // REST API
+ .Map(For.Paths("customer/reviews")) // MongoDB
+ .Map(For.Paths("customer/analytics"))) // EF Core
+ .End();
+```
+
+### Custom Query Engines
+
+Add support for any data source by implementing `IQueryEngine`:
+
+```csharp
+public class RedisQueryEngine : IQueryEngine
+{
+ private readonly IConnectionMultiplexer _redis;
+
+ public RedisQueryEngine(IConnectionMultiplexer redis)
+ {
+ _redis = redis;
+ }
+
+ public bool CanExecute(IQuery query) => query is IRedisQuery;
+
+ public async Task Execute(IQuery query)
+ {
+ var redisQuery = (IRedisQuery)query;
+ return await redisQuery.Run(_redis.GetDatabase());
+ }
+}
+
+// Register alongside built-in adapters
+services.UseDataFuse()
+ .WithEngine(c => new RedisQueryEngine(redisConnection))
+ .WithEngine(c => new QueryEngine(sqlConfiguration))
+ .WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase))
+ // ...
+```
+
+### Path Matching
+
+DataFuse supports XPath and JSONPath patterns for schema paths:
+
+**XPath patterns:**
+- `customer` â exact match
+- `customer/orders` â nested path
+- `customer/orders/order/items` â deep nesting
+
+**JSONPath patterns:**
+- `$.customer` â root level
+- `$.customer.orders` â nested property
+- `$.customer.orders[*].items` â array elements
+
+Register your preferred matcher:
+```csharp
+services.UseDataFuse()
+ .WithPathMatcher(c => new XPathMatcher()) // or JPathMatcher
+```
+
+---
+
+## Architecture
+
+### Execution Flow
+
+```
+Client Request
+ |
+ v
+DataProvider
+ |
+ v
+QueryBuilder â filters by SchemaPaths, resolves dependencies, builds execution plan
+ |
+ v
+QueryExecutor â executes level-by-level, parallelizes siblings, propagates results
+ |
+ v
+EntityBuilder â applies transformers in dependency order, assembles final entity
+ |
+ v
+Fully Hydrated Entity
+```
+
+### Component Responsibilities
+
+| Component | Responsibility |
+|---|---|
+| `DataProvider` | Main orchestrator â coordinates the full pipeline |
+| `QueryBuilder` | Filters queries by requested schema paths, resolves parent-child dependencies |
+| `QueryExecutor` | Executes queries level-by-level with parallel processing of siblings |
+| `EntityBuilder` | Matches results to transformers and builds the final entity |
+| `IQueryEngine` | Adapter interface â each data source implements this |
+| `EntityConfiguration` | Declares the schema: query-transform-path mappings |
+
+### Configuration Patterns
+
+**Linear** â flat entity:
+```csharp
+return CreateSchema.For()
+ .Map(For.Paths("customer"))
+ .Map(For.Paths("customer/address"))
+ .End();
+```
+
+**Branching** â multiple children:
+```csharp
+return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ c => c.Dependents
+ .Map(For.Paths("customer/contact"))
+ .Map(For.Paths("customer/preferences")))
+ .End();
+```
+
+**Deep nesting** â up to 5 levels:
+```csharp
+return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ c => c.Dependents
+ .Map(For.Paths("customer/orders"),
+ o => o.Dependents
+ .Map(For.Paths("customer/orders/order/items"))))
+ .End();
+```
+
+---
+
+## Best Practices
+
+### Query Design
+- Keep queries focused â one query per data concern
+- Use `CollectionResult` for queries returning multiple records
+- Return `null` from `GetQuery` to conditionally skip execution
+- Use `[CacheResult]` for expensive, reusable query results
+
+### Transformer Design
+- Always handle null query results gracefully
+- Initialize collections to prevent null reference exceptions
+- Keep transformers focused on mapping â avoid business logic
+- Use `Context.Request` for conditional transformation
+
+### Schema Design
+- Use meaningful, hierarchical path names that mirror your entity structure
+- Keep nesting depth reasonable (3-4 levels is typical)
+- Use selective loading for performance-sensitive endpoints
+
+### DI Registration
+```csharp
+services.UseDataFuse()
+ .WithEngine(c => new QueryEngine(sqlConfig)) // SQL
+ .WithEngine() // REST API
+ .WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase)) // MongoDB
+ .WithPathMatcher(c => new XPathMatcher())
+ .WithEntityConfiguration(c => new CustomerConfiguration())
+ .WithEntityConfiguration(c => new ProductConfiguration());
+
+services.AddLogging();
+services.AddHttpClient();
+```
+
+---
+
+## Getting Support
+
+- **GitHub**: [github.com/CodeShayk/DataFuse.Net](https://github.com/CodeShayk/DataFuse.Net)
+- **Issues**: [Report bugs and feature requests](https://github.com/CodeShayk/DataFuse.Net/issues)
+- **Wiki**: [Developer guide and documentation](https://github.com/CodeShayk/DataFuse.Net/wiki)
+- **Samples**: Check example projects in the repository for real-world usage patterns
diff --git a/docs/v3.0.0-Release_Notes.md b/docs/v3.0.0-Release_Notes.md
new file mode 100644
index 0000000..0f8ba7f
--- /dev/null
+++ b/docs/v3.0.0-Release_Notes.md
@@ -0,0 +1,127 @@
+# DataFuse v3.0.0 Release Notes
+
+**Release Date:** March 30, 2026
+
+DataFuse v3.0.0 is a major release that introduces the new **MongoDB adapter**, **transform hooks**, **query result caching**, and **multi-target framework support**. This release also completes the project rebrand from Schemio to DataFuse, which includes breaking namespace and package changes.
+
+---
+
+## New Features
+
+### MongoDB Adapter
+
+New `DataFuse.Adapters.MongoDB` package for aggregating data from MongoDB collections alongside SQL, REST API, and Entity Framework sources.
+
+- Built on MongoDB Driver 3.4.0
+- Implements the same query/engine pattern as other adapters
+- Register via `.WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase))`
+
+```csharp
+public class ReviewsMongoQuery : MongoQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult;
+ return async database =>
+ {
+ var collection = database.GetCollection("reviews");
+ var reviews = await collection.Find(r => r.ProductId == product.Id).ToListAsync();
+ return new CollectionResult(reviews);
+ };
+ }
+}
+```
+
+### Transform Hooks
+
+Pre and post transformation hooks provide fine-grained control over the data transformation pipeline.
+
+- **PreTransform hooks** execute before a transformation and can cancel it via `context.Cancel()`
+- **PostTransform hooks** execute after a transformation and can request repetition via `context.Repeat()`
+
+### Query Result Caching
+
+New `CacheResultAttribute` allows marking expensive query results for automatic caching to improve performance.
+
+### Multi-Target Framework Support
+
+All packages (except EntityFramework) now target multiple frameworks:
+
+- `netstandard2.1`
+- `net8.0`
+- `net9.0`
+- `net10.0`
+
+`DataFuse.Adapters.EntityFramework` targets `net10.0` only (EF Core 10.0 dependency).
+
+---
+
+## Breaking Changes
+
+### Project Rename (Schemio to DataFuse)
+
+All namespaces, packages, and registration APIs have been renamed:
+
+| v2.x (Schemio) | v3.0.0 (DataFuse) |
+|-----------------------------|--------------------------------------|
+| `Schemio.Core` (contracts) | `DataFuse.Adapters.Abstraction` |
+| `Schemio.Core` (impl) | `DataFuse.Integration` |
+| `Schemio.SQL` | `DataFuse.Adapters.SQL` |
+| `Schemio.EntityFramework` | `DataFuse.Adapters.EntityFramework` |
+| `Schemio.API` | `DataFuse.Adapters.WebAPI` |
+
+### DI Registration
+
+```csharp
+// Before (v2.x)
+services.UseSchemio(new SchemioOptionsBuilder() ...);
+
+// After (v3.0.0)
+services.UseDataFuse(new DataFuseOptionsBuilder() ...);
+```
+
+### Interface Renames
+
+- `ISchemioOptions` â `IDataFuseOptions`
+- `SchemioOptionsBuilder` â `DataFuseOptionsBuilder`
+
+### NuGet Package Names
+
+All package IDs have changed. Update your package references:
+
+| Old Package | New Package |
+|------------------------|--------------------------------------|
+| `Schemio.Core` | `DataFuse.Adapters.Abstraction` |
+| `Schemio.Core` | `DataFuse.Integration` |
+| `Schemio.SQL` | `DataFuse.Adapters.SQL` |
+| `Schemio.EntityFramework` | `DataFuse.Adapters.EntityFramework` |
+| `Schemio.API` | `DataFuse.Adapters.WebAPI` |
+
+---
+
+## Migration Guide
+
+1. **Update NuGet packages** to the new `DataFuse.*` package names
+2. **Update `using` statements** from `Schemio.*` namespaces to `DataFuse.*`
+3. **Update DI registration** from `UseSchemio()` to `UseDataFuse()` and `SchemioOptionsBuilder` to `DataFuseOptionsBuilder`
+4. **Update target framework** if needed â packages now support `netstandard2.1`, `net8.0`, `net9.0`, and `net10.0`
+
+---
+
+## Packages
+
+| Package | Version | Frameworks |
+|--------------------------------------|---------|----------------------------------------------|
+| `DataFuse.Adapters.Abstraction` | 3.0.0 | netstandard2.1, net8.0, net9.0, net10.0 |
+| `DataFuse.Integration` | 3.0.0 | netstandard2.1, net8.0, net9.0, net10.0 |
+| `DataFuse.Adapters.SQL` | 3.0.0 | netstandard2.1, net8.0, net9.0, net10.0 |
+| `DataFuse.Adapters.EntityFramework` | 3.0.0 | net10.0 |
+| `DataFuse.Adapters.WebAPI` | 3.0.0 | netstandard2.1, net8.0, net9.0, net10.0 |
+| `DataFuse.Adapters.MongoDB` | 3.0.0 | netstandard2.1, net8.0, net9.0, net10.0 |
+
+---
+
+## Repository
+
+- **GitHub:** [CodeShayk/DataFuse.Net](https://github.com/CodeShayk/DataFuse.Net)
diff --git a/docs/wiki.md b/docs/wiki.md
new file mode 100644
index 0000000..8fd38dd
--- /dev/null
+++ b/docs/wiki.md
@@ -0,0 +1,1218 @@
+# DataFuse Framework
+
+### Like GraphQL, but for your heterogeneous backend systems
+
+**DataFuse** is a declarative .NET framework that aggregates data from SQL databases, REST APIs, MongoDB, and Entity Framework into unified, strongly-typed objects â replacing hundreds of lines of manual orchestration code with a clean, schema-driven configuration.
+
+[](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)
+[](https://github.com/CodeShayk/DataFuse.Net/blob/master/LICENSE.md)
+[](https://github.com/CodeShayk/DataFuse.Net/releases/latest)
+
+---
+
+## Table of Contents
+
+1. [Real-World Use Cases](#real-world-use-cases)
+2. [Why DataFuse?](#why-datafuse)
+3. [Quick Start (5 Minutes)](#quick-start)
+4. [Core Concepts](#core-concepts)
+5. [Packages](#packages)
+6. [Query Implementation Guide](#query-implementation-guide)
+7. [Transformer Guide](#transformer-guide)
+8. [Advanced Features](#advanced-features)
+9. [Architecture](#architecture)
+10. [Best Practices](#best-practices)
+11. [Migrating from Schemio to DataFuse](#migrating-from-schemio-v2x-to-datafuse-v300)
+12. [Getting Support](#getting-support)
+
+---
+
+## Real-World Use Cases
+
+### 1. E-Commerce Product Page
+
+Your product page needs data from **three different systems**: inventory from a SQL Server database, live pricing from a pricing microservice REST API, and customer reviews from MongoDB.
+
+**Without DataFuse** â you write this every time:
+
+```csharp
+// 50+ lines of manual orchestration, repeated across your codebase
+public async Task GetProductPage(int productId)
+{
+ var product = await _db.QueryFirstAsync(
+ "SELECT * FROM Products WHERE Id = @Id", new { Id = productId });
+
+ var pricing = await _httpClient.GetFromJsonAsync(
+ $"https://pricing-api/products/{productId}");
+
+ var reviews = await _mongoDb.GetCollection("reviews")
+ .Find(r => r.ProductId == productId).ToListAsync();
+
+ // Manual assembly â error-prone, no caching, no parallel execution
+ return new ProductPage
+ {
+ ProductId = product.Id,
+ Name = product.Name,
+ Description = product.Description,
+ CurrentPrice = pricing.Price,
+ DiscountPercent = pricing.Discount,
+ Reviews = reviews.Select(r => new Review
+ {
+ Rating = r.Stars,
+ Comment = r.Text,
+ Author = r.AuthorName
+ }).ToArray(),
+ AverageRating = reviews.Average(r => r.Stars)
+ };
+}
+```
+
+**With DataFuse** â declare your schema once, use everywhere:
+
+```csharp
+public class ProductPageConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("product"),
+ product => product.Dependents
+ .Map(For.Paths("product/pricing"))
+ .Map(For.Paths("product/reviews")))
+ .End();
+ }
+}
+
+// Usage â one line to get fully hydrated data
+var productPage = dataProvider.GetData(new ProductRequest { ProductId = 42 });
+```
+
+DataFuse automatically:
+- Executes the SQL product query first
+- Runs pricing and reviews API calls **in parallel** (they're siblings)
+- Passes the product result to dependent queries so they know which product to fetch
+- Assembles the final `ProductPage` object via type-safe transformers
+
+### 2. Customer 360 Dashboard
+
+Build a unified customer view pulling from a CRM database, a billing REST API, and a support ticket system:
+
+```csharp
+public class Customer360Configuration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ customer => customer.Dependents
+ .Map(For.Paths("customer/billing"))
+ .Map(For.Paths("customer/tickets"))
+ .Map(For.Paths("customer/orders"),
+ orders => orders.Dependents
+ .Map(
+ For.Paths("customer/orders/order/items"))))
+ .End();
+ }
+}
+```
+
+Need just the basic profile without orders? Use **selective loading**:
+
+```csharp
+var basicProfile = dataProvider.GetData(new CustomerRequest
+{
+ CustomerId = 123,
+ SchemaPaths = new[] { "customer", "customer/billing" }
+});
+```
+
+### 3. Multi-Service Reporting
+
+Aggregate metrics from multiple microservices into a single report object, mixing SQL databases with REST APIs:
+
+```csharp
+public class SalesReportConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("report"),
+ report => report.Dependents
+ .Map(For.Paths("report/inventory"))
+ .Map(For.Paths("report/shipping"))
+ .Map(For.Paths("report/revenue")))
+ .End();
+ }
+}
+```
+
+---
+
+## Why DataFuse?
+
+### The Problem
+
+In modern architectures, a single page or API response often needs data from **multiple backend systems** â SQL databases, REST APIs, MongoDB, third-party services, caches. The standard approach is to write manual orchestration code for each scenario. This leads to:
+
+- **Boilerplate explosion**: Every new data combination means another 50+ lines of fetch-assemble-transform code
+- **No parallelism by default**: Developers write sequential calls unless they manually add `Task.WhenAll`
+- **Tight coupling**: Changing a data source means rewriting orchestration code
+- **No selective loading**: You fetch everything even when the consumer only needs a subset
+- **Inconsistent patterns**: Every developer solves the same problem differently
+
+### How DataFuse Solves This
+
+DataFuse provides a **declarative, schema-driven approach** where you:
+
+1. **Define** your entity (the shape of the data you want)
+2. **Configure** a schema mapping queries to entity paths
+3. **Let DataFuse handle** execution order, parallelism, dependency passing, and assembly
+
+### DataFuse vs Alternatives
+
+| Capability | Manual Code | GraphQL | MediatR | **DataFuse** |
+|---|---|---|---|---|
+| Multi-source aggregation | Manual wiring | Resolver-based | Manual wiring | **Declarative schema** |
+| Parallel execution | Manual `Task.WhenAll` | Per-resolver | Manual | **Automatic** |
+| Selective loading | Manual if/else | Built-in | Manual | **Schema path filtering** |
+| Dependency management | Manual ordering | Implicit | Manual | **Parent-child hierarchy** |
+| Type safety | Varies | Schema-based | Yes | **Strongly typed** |
+| New data source support | Rewrite orchestration | New resolver | New handler | **Add adapter (SQL, API, MongoDB, EF, custom)** |
+| Learning curve | None | High (new language) | Low | **Low (C# only)** |
+| Backend-only (no client changes) | Yes | No (client queries) | Yes | **Yes** |
+
+### When to Use DataFuse
+
+**Use DataFuse when:**
+- Your data lives across **different systems** (SQL + APIs + external services)
+- You need to **compose complex object graphs** from multiple sources
+- You want **automatic parallelism** without managing it yourself
+- You need **selective loading** â different consumers need different subsets of data
+- You're building **API gateways**, **BFF patterns**, or **composite APIs**
+
+**Use plain Dapper/EF Core when:**
+- All your data is in a single database
+- Simple queries with SQL joins suffice
+
+**Use GraphQL when:**
+- You need client-controlled query shapes
+- You're building a public API where consumers define what they need
+
+---
+
+## Quick Start
+
+Get up and running in 5 minutes.
+
+### 1. Install Packages
+
+```bash
+dotnet add package DataFuse.Integration
+dotnet add package DataFuse.Adapters.SQL # For SQL with Dapper
+dotnet add package DataFuse.Adapters.WebAPI # For REST APIs
+dotnet add package DataFuse.Adapters.MongoDB # For MongoDB
+dotnet add package DataFuse.Adapters.EntityFramework # For EF Core
+```
+
+### 2. Define Your Entity
+
+```csharp
+public class Product : IEntity
+{
+ public int ProductId { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public Category Category { get; set; }
+ public Review[] Reviews { get; set; }
+}
+```
+
+### 3. Create Queries
+
+**SQL query** (fetches product from database):
+```csharp
+public class ProductQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (ProductRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ "SELECT ProductId as Id, Name, Price, CategoryId FROM Products WHERE ProductId = @Id",
+ new { Id = request.ProductId });
+ }
+}
+```
+
+**MongoDB query** (fetches reviews from MongoDB):
+```csharp
+public class ReviewsMongoQuery : MongoQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult? parentQueryResult)
+ {
+ var product = (ProductResult)parentQueryResult; // Parent result is available
+ return async database =>
+ {
+ var collection = database.GetCollection("reviews");
+ var reviews = await collection.Find(r => r.ProductId == product.Id).ToListAsync();
+ return new CollectionResult(reviews);
+ };
+ }
+}
+```
+
+### 4. Create Transformers
+
+```csharp
+public class ProductTransform : BaseTransformer
+{
+ public override void Transform(ProductResult queryResult, Product entity)
+ {
+ entity.ProductId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ entity.Price = queryResult.Price;
+ }
+}
+
+public class ReviewsTransform : BaseTransformer, Product>
+{
+ public override void Transform(CollectionResult queryResult, Product entity)
+ {
+ entity.Reviews = queryResult?.Select(r => new Review
+ {
+ ReviewId = r.Id, Comment = r.Comment, Rating = r.Rating
+ }).ToArray() ?? Array.Empty();
+ }
+}
+```
+
+### 5. Configure the Schema
+
+```csharp
+public class ProductConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("product"),
+ product => product.Dependents
+ .Map(For.Paths("product/category"))
+ .Map(For.Paths("product/reviews")))
+ .End();
+ }
+}
+```
+
+### 6. Register with DI
+
+```csharp
+services.UseDataFuse()
+ .WithEngine(c => new QueryEngine(sqlConfiguration)) // SQL adapter
+ .WithEngine() // Web API adapter
+ .WithEngine(c => new DataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase)) // MongoDB adapter
+ .WithPathMatcher(c => new XPathMatcher())
+ .WithEntityConfiguration(c => new ProductConfiguration());
+
+services.AddHttpClient();
+```
+
+### 7. Use It
+
+```csharp
+public class ProductService
+{
+ private readonly IDataProvider _dataProvider;
+
+ public ProductService(IDataProvider dataProvider)
+ {
+ _dataProvider = dataProvider;
+ }
+
+ public Product GetProduct(int productId)
+ {
+ return _dataProvider.GetData(new ProductRequest { ProductId = productId });
+ }
+
+ // Selective loading â only fetch product + reviews, skip category
+ public Product GetProductWithReviews(int productId)
+ {
+ return _dataProvider.GetData(new ProductRequest
+ {
+ ProductId = productId,
+ SchemaPaths = new[] { "product", "product/reviews" }
+ });
+ }
+}
+```
+
+---
+
+## Core Concepts
+
+### Entities
+
+Entities represent the final aggregated data structure. They implement `IEntity` and define the complete object graph that DataFuse will hydrate from multiple sources:
+
+```csharp
+public class Customer : IEntity
+{
+ public int CustomerId { get; set; }
+ public string Name { get; set; }
+
+ // Each of these can come from a different data source
+ public Communication Communication { get; set; } // From REST API
+ public Address Address { get; set; } // From SQL database
+ public Order[] Orders { get; set; } // From EF Core
+}
+```
+
+### Queries
+
+Queries fetch data from a specific source. DataFuse provides base classes for common sources:
+
+| Base Class | Source | Adapter Package |
+|---|---|---|
+| `SQLQuery` | SQL databases via Dapper | `DataFuse.Adapters.SQL` |
+| `SQLQuery` (EF) | Entity Framework Core | `DataFuse.Adapters.EntityFramework` |
+| `MongoQuery` | MongoDB collections | `DataFuse.Adapters.MongoDB` |
+| `WebQuery` | REST APIs via HttpClient | `DataFuse.Adapters.WebAPI` |
+
+#### Parent-Child Query Dependencies
+
+Child queries receive their parent's result, enabling dependent data fetching:
+
+```csharp
+// Root query â fetches customer from database
+public class CustomerQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ "SELECT CustomerId as Id, Name, Code FROM Customers WHERE CustomerId = @Id",
+ new { Id = request.CustomerId });
+ }
+}
+
+// Child query â uses parent's CustomerId to fetch orders
+public class OrdersQuery : SQLQuery>
+{
+ protected override Func>> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var customer = (CustomerResult)parentQueryResult;
+ return async connection =>
+ {
+ var orders = await connection.QueryAsync(
+ "SELECT OrderId, OrderNumber, OrderDate FROM Orders WHERE CustomerId = @Id",
+ new { Id = customer.Id });
+ return new CollectionResult(orders);
+ };
+ }
+}
+```
+
+#### Execution Order
+
+```
+1. Root Query (CustomerQuery) executes first
+ |
+ v CustomerResult passed to children
+
+2. Child Queries execute IN PARALLEL:
+ - OrdersQuery (uses CustomerId)
+ - CommunicationQuery (uses CustomerId)
+ - AddressQuery (uses CustomerId)
+ |
+ v OrderResult passed to grandchildren
+
+3. Grandchild Queries execute:
+ - OrderItemsQuery (uses OrderId from OrderResult)
+```
+
+Queries at the same level run in parallel automatically. DataFuse manages the dependency tree.
+
+### Transformers
+
+Transformers map query results onto the entity. Each query has a paired transformer:
+
+```csharp
+public class CustomerTransform : BaseTransformer
+{
+ public override void Transform(CustomerResult queryResult, Customer entity)
+ {
+ entity.CustomerId = queryResult.Id;
+ entity.Name = queryResult.Name;
+ }
+}
+
+public class OrdersTransform : BaseTransformer, Customer>
+{
+ public override void Transform(CollectionResult queryResult, Customer entity)
+ {
+ entity.Orders = queryResult?.Select(o => new Order
+ {
+ OrderId = o.OrderId,
+ OrderNumber = o.OrderNumber,
+ OrderDate = o.OrderDate
+ }).ToArray() ?? Array.Empty();
+ }
+}
+```
+
+### Schema Configuration
+
+The schema defines the full query-transform-path hierarchy:
+
+```csharp
+public class CustomerConfiguration : EntityConfiguration
+{
+ public override IEnumerable> GetSchema()
+ {
+ return CreateSchema.For()
+ .Map(For.Paths("customer"),
+ customer => customer.Dependents
+ .Map(
+ For.Paths("customer/communication"))
+ .Map(For.Paths("customer/orders"),
+ orders => orders.Dependents
+ .Map(
+ For.Paths("customer/orders/order/items"))))
+ .End();
+ }
+}
+```
+
+Schema paths correspond to the entity's object graph:
+- `customer` â root properties
+- `customer/communication` â Customer.Communication
+- `customer/orders` â Customer.Orders collection
+- `customer/orders/order/items` â Order.Items for each order
+
+---
+
+## Packages
+
+### DataFuse.Integration
+
+Core package with orchestration, DI extensions, helpers, and path matchers.
+
+```bash
+dotnet add package DataFuse.Integration
+```
+
+**Key components:** `DataProvider`, `QueryBuilder`, `EntityBuilder`, `DataFuseOptionsBuilder`, XPath/JSONPath matchers, DI registration via `UseDataFuse()`.
+
+### DataFuse.Adapters.Abstraction
+
+Interfaces and base classes: `IEntity`, `IQuery`, `IQueryResult`, `ITransformer`, `IQueryEngine`, `BaseQuery`, `BaseTransformer`, `EntityConfiguration`, `CreateSchema`, `CollectionResult`, `CacheResultAttribute`.
+
+### DataFuse.Adapters.SQL
+
+SQL database support using Dapper.
+
+```bash
+dotnet add package DataFuse.Adapters.SQL
+```
+
+Supports SQL Server, SQLite, MySQL, PostgreSQL, Oracle.
+
+### DataFuse.Adapters.EntityFramework
+
+Entity Framework Core integration.
+
+```bash
+dotnet add package DataFuse.Adapters.EntityFramework
+```
+
+Full LINQ support, DbContext factory integration.
+
+### DataFuse.Adapters.MongoDB
+
+MongoDB support using the official MongoDB driver.
+
+```bash
+dotnet add package DataFuse.Adapters.MongoDB
+```
+
+Full `IMongoDatabase` access, LINQ and filter builder support.
+
+### DataFuse.Adapters.WebAPI
+
+REST API support using HttpClient.
+
+```bash
+dotnet add package DataFuse.Adapters.WebAPI
+```
+
+Request/response header management, JSON deserialization.
+
+### Compatibility
+
+| Package | Target Frameworks |
+|---|---|
+| DataFuse.Adapters.Abstraction | netstandard2.1, net8.0, net9.0, net10.0 |
+| DataFuse.Integration | netstandard2.1, net8.0, net9.0, net10.0 |
+| DataFuse.Adapters.SQL | netstandard2.1, net8.0, net9.0, net10.0 |
+| DataFuse.Adapters.EntityFramework | net10.0 |
+| DataFuse.Adapters.MongoDB | netstandard2.1, net8.0, net9.0, net10.0 |
+| DataFuse.Adapters.WebAPI | netstandard2.1, net8.0, net9.0, net10.0 |
+
+---
+
+## Query Implementation Guide
+
+### SQL Queries (Dapper)
+
+```csharp
+// Single result
+public class CustomerQuery : SQLQuery
+{
+ protected override Func> GetQuery(
+ IDataContext context, IQueryResult parentQueryResult)
+ {
+ var request = (CustomerRequest)context.Request;
+ return connection => connection.QueryFirstOrDefaultAsync(
+ @"SELECT CustomerId as Id, CustomerName as Name, CustomerCode as Code
+ FROM Customers WHERE CustomerId = @CustomerId",
+ new { CustomerId = request.CustomerId });
+ }
+}
+
+// Collection result
+public class OrdersQuery : SQLQuery>
+{
+ protected override Func