├── .editorconfig
├── .gitattributes
├── .github
├── CODEOWNERS
├── FUNDING.yml
├── renovate.json
├── settings.yml
└── workflows
│ ├── ci.yml
│ └── labeled.yml
├── .gitignore
├── Directory.Build.props
├── LICENSE
├── MicroOrm.Dapper.Repositories.sln
├── README.md
├── dapper-plus-sponsor.png
├── entity-framework-extensions-sponsor.png
├── icon.png
├── src
├── Attributes
│ ├── IdentityAttribute.cs
│ ├── IgnoreUpdateAttribute.cs
│ ├── Joins
│ │ ├── CrossJoinAttribute.cs
│ │ ├── InnerJoinAttribute.cs
│ │ ├── JoinAttributeBase.cs
│ │ ├── LeftJoinAttribute.cs
│ │ └── RightJoinAttribute.cs
│ ├── LogicalDelete
│ │ ├── DeletedAttribute.cs
│ │ └── StatusAttribute.cs
│ └── UpdatedAtAttribute.cs
├── Config
│ └── MicroOrmConfig.cs
├── DapperRepository.BulkInsert.cs
├── DapperRepository.BulkUpdate.cs
├── DapperRepository.Delete.cs
├── DapperRepository.ExecuteJoinQuery.cs
├── DapperRepository.Insert.cs
├── DapperRepository.Update.cs
├── DapperRepository.cs
├── DbContext
│ ├── DapperDbContext.cs
│ └── IDapperDbContext.cs
├── Extensions
│ ├── CollectionExtensions.cs
│ ├── OracleDynamicParametersExtensions.cs
│ └── TypeExtensions.cs
├── IDapperRepository.cs
├── IReadOnlyDapperRepository.cs
├── MicroOrm.Dapper.Repositories.csproj
├── ReadOnlyDapperRepository.Count.Join.cs
├── ReadOnlyDapperRepository.Count.cs
├── ReadOnlyDapperRepository.Find.Join.cs
├── ReadOnlyDapperRepository.Find.cs
├── ReadOnlyDapperRepository.FindAll.Join.cs
├── ReadOnlyDapperRepository.FindAll.cs
├── ReadOnlyDapperRepository.FindAllBetween.cs
├── ReadOnlyDapperRepository.FindById.Join.cs
├── ReadOnlyDapperRepository.FindById.cs
├── ReadOnlyDapperRepository.SetGroupBy.cs
├── ReadOnlyDapperRepository.SetLimit.cs
├── ReadOnlyDapperRepository.SetOrderBy.cs
├── ReadOnlyDapperRepository.SetSelect.cs
├── ReadOnlyDapperRepository.cs
└── SqlGenerator
│ ├── ExpressionHelper.cs
│ ├── Filters
│ ├── FilterData.cs
│ ├── GroupInfo.cs
│ ├── LimitInfo.cs
│ ├── OrderInfo.cs
│ └── SelectInfo.cs
│ ├── ISqlGenerator.cs
│ ├── QueryExpressions
│ ├── QueryBinaryExpression.cs
│ ├── QueryExpression.cs
│ ├── QueryExpressionType.cs
│ └── QueryParameterExpression.cs
│ ├── SqlGenerator.AppendJoin.cs
│ ├── SqlGenerator.AppendWherePredicateQuery.cs
│ ├── SqlGenerator.GetBulkInsert.cs
│ ├── SqlGenerator.GetBulkUpdate.cs
│ ├── SqlGenerator.GetCount.cs
│ ├── SqlGenerator.GetDelete.cs
│ ├── SqlGenerator.GetInsert.cs
│ ├── SqlGenerator.GetQueryProperties.cs
│ ├── SqlGenerator.GetSelect.cs
│ ├── SqlGenerator.GetTableName.cs
│ ├── SqlGenerator.GetUpdate.cs
│ ├── SqlGenerator.InitConfig.cs
│ ├── SqlGenerator.InitLogicalDeleted.cs
│ ├── SqlGenerator.InitProperties.cs
│ ├── SqlGenerator.cs
│ ├── SqlJoinPropertyMetadata.cs
│ ├── SqlPropertyMetadata.cs
│ ├── SqlProvider.cs
│ └── SqlQuery.cs
└── tests
├── .editorconfig
├── .env
├── Repositories.Base
├── BaseDbContextTests.cs
├── BaseRepositoriesTests.cs
├── DotEnv.cs
├── InitData.cs
├── RandomGenerator.cs
├── Repositories.Base.csproj
└── TestDbContext.cs
├── Repositories.MSSQL.Tests
├── DatabaseFixture.cs
├── MicrosoftDatabaseFixture.cs
├── MicrosoftDbContextTests.cs
├── MicrosoftRepositoriesTests.cs
├── Repositories.MSSQL.Tests.csproj
├── RepositoriesTests.cs
├── SystemDatabaseFixture.cs
├── SystemDbContextTests.cs
└── SystemRepositoriesTests.cs
├── Repositories.MySql.Tests
├── DatabaseFixture.cs
├── MySqlClientDatabaseFixture.cs
├── MySqlClientDbContextTests.cs
├── MySqlClientRepositoriesTests.cs
├── MySqlConnectorDatabaseFixture.cs
├── MySqlConnectorDbContextTests.cs
├── MySqlConnectorRepositoriesTests.cs
├── Repositories.MySql.Tests.csproj
└── RepositoriesTests.cs
├── Repositories.Oracle.Tests
├── DatabaseFixture.cs
├── DbContextTests.cs
├── Repositories.Oracle.Tests.csproj
└── RepositoriesTests.cs
├── Repositories.PostgreSQL.Tests
├── DatabaseFixture.cs
├── DbContextTests.cs
├── Repositories.PostgreSQL.Tests.csproj
└── RepositoriesTests.cs
├── Repositories.SQLite.Tests
├── DatabaseFixture.cs
├── MicrosoftDatabaseFixture.cs
├── MicrosoftDbContextTests.cs
├── MicrosoftRepositoriesTests.cs
├── Repositories.SQLite.Tests.csproj
├── RepositoriesTests.cs
├── SystemDatabaseFixture.cs
├── SystemDbContextTests.cs
└── SystemRepositoriesTests.cs
├── SqlGenerator.Tests
├── ExpressionHelperTests.cs
├── GetKeysParamTests.cs
├── MsSqlGeneratorTests.cs
├── MySqlGeneratorTests.cs
├── OracleSqlGeneratorTests.cs
├── PostgresSqlGeneratorTests.cs
├── SQLiteGeneratorTests.cs
└── SqlGenerator.Tests.csproj
├── TestClasses
├── Address.cs
├── AddressKeyAsIdentity.cs
├── BaseEntity.cs
├── Car.cs
├── City.cs
├── ComplicatedObj.cs
├── Phone.cs
├── Report.cs
├── TestClasses.csproj
└── User.cs
└── docker-compose.yml
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | max_line_length = 100
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.cs]
13 | indent_size = 4
14 | max_line_length = 160
15 |
16 | ## Dotnet code style settings:
17 |
18 | # Sort using and Import directives with System.* appearing first
19 | dotnet_sort_system_directives_first = true
20 | # Avoid "this." and "Me." if not necessary
21 | dotnet_style_qualification_for_field = false:suggestion
22 | dotnet_style_qualification_for_property = false:suggestion
23 | dotnet_style_qualification_for_method = false:suggestion
24 | dotnet_style_qualification_for_event = false:suggestion
25 |
26 | # Use language keywords instead of framework type names for type references
27 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
28 | dotnet_style_predefined_type_for_member_access = true:suggestion
29 |
30 | # Suggest more modern language features when available
31 | dotnet_style_object_initializer = true:suggestion
32 | dotnet_style_collection_initializer = true:suggestion
33 | dotnet_style_coalesce_expression = true:suggestion
34 | dotnet_style_null_propagation = true:suggestion
35 | dotnet_style_explicit_tuple_names = true:suggestion
36 |
37 | # CSharp code style settings:
38 |
39 | # Prefer "var" everywhere
40 | csharp_style_var_for_built_in_types = false:none
41 | csharp_style_var_when_type_is_apparent = true:suggestion
42 | csharp_style_var_elsewhere = true:suggestion
43 |
44 | # Prefer method-like constructs to have a block body
45 | csharp_style_expression_bodied_methods = false:none
46 | csharp_style_expression_bodied_constructors = false:none
47 | csharp_style_expression_bodied_operators = false:none
48 |
49 | # Prefer property-like constructs to have an expression-body
50 | csharp_style_expression_bodied_properties = true:none
51 | csharp_style_expression_bodied_indexers = true:none
52 | csharp_style_expression_bodied_accessors = true:none
53 |
54 | # Suggest more modern language features when available
55 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
56 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
57 | csharp_style_inlined_variable_declaration = true:suggestion
58 | csharp_style_throw_expression = true:suggestion
59 | csharp_style_conditional_delegate_call = true:suggestion
60 |
61 | # Newline settings
62 | csharp_new_line_before_else = true
63 | csharp_new_line_before_catch = true
64 | csharp_new_line_before_finally = true
65 |
66 | ## Naming
67 |
68 | ### private fields should be _camelCase
69 |
70 | dotnet_naming_style.underscore_prefix.capitalization = camel_case
71 | dotnet_naming_style.underscore_prefix.required_prefix = _
72 |
73 | dotnet_naming_rule.private_fields_with_underscore.symbols = private_fields
74 | dotnet_naming_rule.private_fields_with_underscore.style = underscore_prefix
75 | dotnet_naming_rule.private_fields_with_underscore.severity = suggestion
76 |
77 | dotnet_naming_symbols.private_fields.applicable_kinds = field
78 | dotnet_naming_symbols.private_fields.applicable_accessibilities = private
79 |
80 | ## Code Quality Analysis
81 | dotnet_diagnostic.CA2007.severity = error # Use ConfigureAwait
82 | configure_await_analysis_mode = library
83 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @phnx47
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: phnx47
2 | ko_fi: phnx47
3 | buy_me_a_coffee: phnx47
4 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [":dependencyDashboard", "group:monorepos"],
4 | "labels": ["dependencies"],
5 | "assignees": ["@phnx47"],
6 | "packageRules": [
7 | {
8 | "automerge": true,
9 | "groupName": "coverlet packages",
10 | "matchSourceUrls": ["https://github.com/coverlet-coverage/coverlet"]
11 | },
12 | {
13 | "automerge": true,
14 | "extends": ["monorepo:vstest", "monorepo:xunit-dotnet"]
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.github/settings.yml:
--------------------------------------------------------------------------------
1 | repository:
2 | has_issues: true
3 | has_projects: false
4 | has_wiki: false
5 | has_downloads: true
6 | default_branch: main
7 | allow_squash_merge: true
8 | allow_merge_commit: true
9 | allow_rebase_merge: true
10 | allow_auto_merge: true
11 | delete_branch_on_merge: true
12 | enable_automated_security_fixes: false
13 | enable_vulnerability_alerts: true
14 |
15 | labels:
16 | - name: dependencies
17 | color: 0052CC
18 | description:
19 |
20 | - name: bug
21 | color: D73A4A
22 | description:
23 |
24 | - name: documentation
25 | color: 0075CA
26 | description:
27 |
28 | - name: duplicate
29 | color: CFD3D7
30 | description:
31 |
32 | - name: enhancement
33 | color: A2EEEF
34 | description:
35 |
36 | - name: good first issue
37 | color: 7057FF
38 | description:
39 |
40 | - name: help wanted
41 | color: 008672
42 | description:
43 |
44 | - name: invalid
45 | color: E4E669
46 | description:
47 |
48 | - name: question
49 | color: D876E3
50 | description:
51 |
52 | - name: wontfix
53 | color: FFFFFF
54 | description:
55 |
56 | - name: vulnerability
57 | color: D1260F
58 | description:
59 |
60 | - name: sync
61 | color: 6E81A3
62 | description:
63 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - "main"
7 | tags:
8 | - "v*"
9 | pull_request:
10 | branches:
11 | - "main"
12 | workflow_dispatch:
13 |
14 | env:
15 | TEST_DB_PASS: "Password12!"
16 |
17 | jobs:
18 | build:
19 | name: Build, Test & Pack
20 | runs-on: ubuntu-24.04
21 | services:
22 | mysql:
23 | image: mysql:8.0-debian
24 | env:
25 | MYSQL_ROOT_PASSWORD: ${{ env.TEST_DB_PASS }}
26 | ports:
27 | - "3306:3306"
28 | mssql:
29 | image: mcr.microsoft.com/mssql/server:2025-latest
30 | env:
31 | ACCEPT_EULA: "Y"
32 | SA_PASSWORD: ${{ env.TEST_DB_PASS }}
33 | ports:
34 | - "1433:1433"
35 | oracle:
36 | image: gvenzl/oracle-xe:21-slim-faststart
37 | env:
38 | ORACLE_PASSWORD: ${{ env.TEST_DB_PASS }}
39 | ports:
40 | - "1521:1521"
41 | postgres:
42 | image: postgres:17.5-alpine
43 | ports:
44 | - "5432:5432"
45 | env:
46 | POSTGRES_PASSWORD: ${{ env.TEST_DB_PASS }}
47 |
48 | steps:
49 | - name: Checkout
50 | uses: actions/checkout@v4
51 | with:
52 | fetch-depth: 0
53 |
54 | - name: Build
55 | run: dotnet build -c Release
56 |
57 | - name: Run tests
58 | run: dotnet test --no-build -c Release
59 |
60 | - name: Publish to Codecov
61 | uses: codecov/codecov-action@v5
62 | with:
63 | fail_ci_if_error: true
64 | token: ${{ secrets.CODECOV_TOKEN }}
65 |
66 | - name: Set Dev version
67 | if: github.ref == 'refs/heads/main'
68 | run: echo "VERSION=$(git describe --long --tags | sed 's/^v//;0,/-/s//./')" >> $GITHUB_ENV
69 |
70 | - name: Set Release version
71 | if: startsWith(github.ref, 'refs/tags/v')
72 | run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
73 |
74 | - name: Pack NuGet artifacts
75 | if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
76 | run: dotnet pack --no-build -c Release -p:PackageVersion="${{ env.VERSION }}" -o packages
77 |
78 | - name: Upload artifacts
79 | if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
80 | uses: actions/upload-artifact@v4
81 | with:
82 | name: packages
83 | path: packages/*nupkg
84 |
85 | github:
86 | name: Deploy to GitHub
87 | needs: [build]
88 | if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
89 | runs-on: ubuntu-24.04
90 | steps:
91 | - name: Download artifacts
92 | uses: actions/download-artifact@v4
93 | with:
94 | name: packages
95 | - name: Push to GitHub
96 | run: |
97 | dotnet nuget push "*.nupkg" \
98 | --skip-duplicate \
99 | -k ${{ secrets.GITHUB_TOKEN }} \
100 | -s https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
101 |
102 | release:
103 | name: Create GitHub release
104 | needs: [build]
105 | if: startsWith(github.ref, 'refs/tags/v')
106 | runs-on: ubuntu-24.04
107 | steps:
108 | - name: Checkout
109 | uses: actions/checkout@v4
110 | - name: Download artifacts
111 | uses: actions/download-artifact@v4
112 | with:
113 | name: packages
114 | path: packages
115 | - name: Create GitHub Release
116 | run: gh release create ${{ github.ref_name }} packages/*nupkg
117 | env:
118 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
119 |
120 | nuget:
121 | name: Deploy to NuGet
122 | needs: [release]
123 | if: startsWith(github.ref, 'refs/tags/v')
124 | runs-on: ubuntu-24.04
125 | steps:
126 | - name: Download artifacts
127 | uses: actions/download-artifact@v4
128 | with:
129 | name: packages
130 | - name: Push to NuGet
131 | run: |
132 | dotnet nuget push "*.nupkg" \
133 | -k ${{ secrets.NUGET_KEY }} \
134 | -s https://api.nuget.org/v3/index.json
135 |
--------------------------------------------------------------------------------
/.github/workflows/labeled.yml:
--------------------------------------------------------------------------------
1 | name: Labeled
2 |
3 | on:
4 | pull_request:
5 | types: [labeled]
6 | branches:
7 | - "main"
8 |
9 | permissions:
10 | pull-requests: write
11 | contents: write
12 |
13 | jobs:
14 | automerge:
15 | name: Enable auto-merge
16 | runs-on: ubuntu-24.04
17 | if: github.actor == 'phnx47-bot' && contains(github.event.pull_request.labels.*.name, 'sync')
18 | steps:
19 | - name: Checkout
20 | uses: actions/checkout@v4
21 |
22 | - name: Run command
23 | run: gh pr merge -s --auto ${{ github.event.pull_request.number }}
24 | env:
25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.nupkg
2 | *.snupkg
3 | *.user
4 | *.opencover.xml
5 | *.orig
6 | .idea
7 | bin
8 | obj
9 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 12.0
4 | false
5 | CS1591;NETSDK1138
6 |
7 |
8 | true
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Serge K
4 | Copyright (c) 2014 Diego García
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/MicroOrm.Dapper.Repositories.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2036
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E409731D-9AB4-4389-B611-53A3AF8324A4}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{94F86B38-C3FB-4FBB-802E-7786C457050D}"
9 | ProjectSection(SolutionItems) = preProject
10 | tests\.env = tests\.env
11 | EndProjectSection
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroOrm.Dapper.Repositories", "src\MicroOrm.Dapper.Repositories.csproj", "{A8258060-EDF7-4713-9428-088ADD6FE503}"
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClasses", "tests\TestClasses\TestClasses.csproj", "{2691E152-7033-4C25-A8D5-4941004BD611}"
16 | EndProject
17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlGenerator.Tests", "tests\SqlGenerator.Tests\SqlGenerator.Tests.csproj", "{0D5ADDAF-B82B-479E-9000-295162C4679B}"
18 | EndProject
19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.Base", "tests\Repositories.Base\Repositories.Base.csproj", "{C927DED2-5B55-4FE8-9F62-C2D8BE4922B6}"
20 | EndProject
21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.MSSQL.Tests", "tests\Repositories.MSSQL.Tests\Repositories.MSSQL.Tests.csproj", "{5049285B-1366-41C2-AD7C-4F70B11BFD5C}"
22 | EndProject
23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.MySql.Tests", "tests\Repositories.MySql.Tests\Repositories.MySql.Tests.csproj", "{E0118ECB-F93A-4297-9D3F-0E2AC7C709A4}"
24 | EndProject
25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.Oracle.Tests", "tests\Repositories.Oracle.Tests\Repositories.Oracle.Tests.csproj", "{9F38EB03-41AD-4CAD-9903-12E0E890FF41}"
26 | EndProject
27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.PostgreSQL.Tests", "tests\Repositories.PostgreSQL.Tests\Repositories.PostgreSQL.Tests.csproj", "{BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repositories.SQLite.Tests", "tests\Repositories.SQLite.Tests\Repositories.SQLite.Tests.csproj", "{5AD638E4-639A-425E-857E-60EB21CBCBC0}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {A8258060-EDF7-4713-9428-088ADD6FE503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {A8258060-EDF7-4713-9428-088ADD6FE503}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {A8258060-EDF7-4713-9428-088ADD6FE503}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {A8258060-EDF7-4713-9428-088ADD6FE503}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {2691E152-7033-4C25-A8D5-4941004BD611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {2691E152-7033-4C25-A8D5-4941004BD611}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {2691E152-7033-4C25-A8D5-4941004BD611}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {2691E152-7033-4C25-A8D5-4941004BD611}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {0D5ADDAF-B82B-479E-9000-295162C4679B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {0D5ADDAF-B82B-479E-9000-295162C4679B}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {0D5ADDAF-B82B-479E-9000-295162C4679B}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {0D5ADDAF-B82B-479E-9000-295162C4679B}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {C927DED2-5B55-4FE8-9F62-C2D8BE4922B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {C927DED2-5B55-4FE8-9F62-C2D8BE4922B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {C927DED2-5B55-4FE8-9F62-C2D8BE4922B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {C927DED2-5B55-4FE8-9F62-C2D8BE4922B6}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {5049285B-1366-41C2-AD7C-4F70B11BFD5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {5049285B-1366-41C2-AD7C-4F70B11BFD5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {5049285B-1366-41C2-AD7C-4F70B11BFD5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
56 | {5049285B-1366-41C2-AD7C-4F70B11BFD5C}.Release|Any CPU.Build.0 = Release|Any CPU
57 | {E0118ECB-F93A-4297-9D3F-0E2AC7C709A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58 | {E0118ECB-F93A-4297-9D3F-0E2AC7C709A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
59 | {E0118ECB-F93A-4297-9D3F-0E2AC7C709A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {E0118ECB-F93A-4297-9D3F-0E2AC7C709A4}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {9F38EB03-41AD-4CAD-9903-12E0E890FF41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {9F38EB03-41AD-4CAD-9903-12E0E890FF41}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {9F38EB03-41AD-4CAD-9903-12E0E890FF41}.Release|Any CPU.ActiveCfg = Release|Any CPU
64 | {9F38EB03-41AD-4CAD-9903-12E0E890FF41}.Release|Any CPU.Build.0 = Release|Any CPU
65 | {BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 | {BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 | {BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
68 | {BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE}.Release|Any CPU.Build.0 = Release|Any CPU
69 | {5AD638E4-639A-425E-857E-60EB21CBCBC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
70 | {5AD638E4-639A-425E-857E-60EB21CBCBC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
71 | {5AD638E4-639A-425E-857E-60EB21CBCBC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {5AD638E4-639A-425E-857E-60EB21CBCBC0}.Release|Any CPU.Build.0 = Release|Any CPU
73 | EndGlobalSection
74 | GlobalSection(SolutionProperties) = preSolution
75 | HideSolutionNode = FALSE
76 | EndGlobalSection
77 | GlobalSection(NestedProjects) = preSolution
78 | {A8258060-EDF7-4713-9428-088ADD6FE503} = {E409731D-9AB4-4389-B611-53A3AF8324A4}
79 | {2691E152-7033-4C25-A8D5-4941004BD611} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
80 | {0D5ADDAF-B82B-479E-9000-295162C4679B} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
81 | {C927DED2-5B55-4FE8-9F62-C2D8BE4922B6} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
82 | {5049285B-1366-41C2-AD7C-4F70B11BFD5C} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
83 | {E0118ECB-F93A-4297-9D3F-0E2AC7C709A4} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
84 | {9F38EB03-41AD-4CAD-9903-12E0E890FF41} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
85 | {BFBD1CAD-3831-4815-A95C-6A43F8E9FAEE} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
86 | {5AD638E4-639A-425E-857E-60EB21CBCBC0} = {94F86B38-C3FB-4FBB-802E-7786C457050D}
87 | EndGlobalSection
88 | GlobalSection(ExtensibilityGlobals) = postSolution
89 | SolutionGuid = {4D543221-E30F-4763-AAC8-A744A0F8D88E}
90 | EndGlobalSection
91 | EndGlobal
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MicroOrm.Dapper.Repositories
2 |
3 | [](https://github.com/phnx47/dapper-repositories/actions/workflows/ci.yml)
4 | [](https://www.nuget.org/packages/MicroOrm.Dapper.Repositories)
5 | [](https://www.nuget.org/packages/MicroOrm.Dapper.Repositories)
6 | [](https://codecov.io/gh/phnx47/dapper-repositories)
7 | [](https://github.com/phnx47/dapper-repositories/blob/main/LICENSE)
8 |
9 |
10 | ## Description
11 |
12 | Lightweight library that extends [Dapper](https://github.com/DapperLib/Dapper) by generating SQL for CRUD operations based on your POCO classes. It simplifies data access by using metadata attributes to build queries automatically, including support for joins, logical deletes, and pagination.
13 |
14 | Read more at [Learn Dapper](https://www.learndapper.com/extensions/microorm-dapper-repositories).
15 |
16 | ## Sponsors
17 |
18 | [Dapper Plus](https://dapper-plus.net/) and [Entity Framework Extensions](https://entityframework-extensions.net/) are major sponsors and are proud to contribute to the development of MicroOrm.Dapper.Repositories
19 |
20 | [](https://dapper-plus.net/bulk-insert)
21 |
22 | [](https://entityframework-extensions.net/bulk-insert)
23 |
24 | ## License
25 |
26 | All contents of this package are licensed under the [MIT license](https://opensource.org/licenses/MIT).
27 |
--------------------------------------------------------------------------------
/dapper-plus-sponsor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phnx47/dapper-repositories/58feffd27c8bb6bb7463ec90de9d41d1d2e4379a/dapper-plus-sponsor.png
--------------------------------------------------------------------------------
/entity-framework-extensions-sponsor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phnx47/dapper-repositories/58feffd27c8bb6bb7463ec90de9d41d1d2e4379a/entity-framework-extensions-sponsor.png
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phnx47/dapper-repositories/58feffd27c8bb6bb7463ec90de9d41d1d2e4379a/icon.png
--------------------------------------------------------------------------------
/src/Attributes/IdentityAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Attributes;
4 |
5 |
6 | ///
7 | /// Identity key
8 | ///
9 | public sealed class IdentityAttribute : Attribute
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/src/Attributes/IgnoreUpdateAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Attributes;
4 |
5 |
6 | ///
7 | /// Ignore property attribute
8 | ///
9 | public sealed class IgnoreUpdateAttribute : Attribute
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/src/Attributes/Joins/CrossJoinAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace MicroOrm.Dapper.Repositories.Attributes.Joins;
2 |
3 |
4 | ///
5 | /// Generate CROSS JOIN
6 | ///
7 | public sealed class CrossJoinAttribute : JoinAttributeBase
8 | {
9 |
10 | ///
11 | /// Constructor
12 | ///
13 | public CrossJoinAttribute()
14 | {
15 | }
16 |
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Name of external table
22 | public CrossJoinAttribute(string tableName)
23 | : base(tableName, string.Empty, string.Empty, string.Empty, string.Empty, "CROSS JOIN")
24 | {
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Attributes/Joins/InnerJoinAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace MicroOrm.Dapper.Repositories.Attributes.Joins;
2 |
3 |
4 | ///
5 | /// Generate INNER JOIN
6 | ///
7 | public sealed class InnerJoinAttribute : JoinAttributeBase
8 | {
9 |
10 | ///
11 | /// Constructor
12 | ///
13 | public InnerJoinAttribute()
14 | {
15 | }
16 |
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Name of external table
22 | /// ForeignKey of this table
23 | /// Key of external table
24 | public InnerJoinAttribute(string tableName, string key, string externalKey)
25 | : base(tableName, key, externalKey, string.Empty, string.Empty, "INNER JOIN")
26 | {
27 | }
28 |
29 |
30 | ///
31 | /// Constructor
32 | ///
33 | /// Name of external table
34 | /// ForeignKey of this table
35 | /// Key of external table
36 | /// Name of external table schema
37 | public InnerJoinAttribute(string tableName, string key, string externalKey, string tableSchema)
38 | : base(tableName, key, externalKey, tableSchema, string.Empty, "INNER JOIN")
39 | {
40 | }
41 |
42 |
43 | ///
44 | /// Constructor
45 | ///
46 | /// Name of external table
47 | /// ForeignKey of this table
48 | /// Key of external table
49 | /// Name of external table schema
50 | /// External table alias
51 | public InnerJoinAttribute(string tableName, string key, string externalKey, string tableSchema, string tableAbbreviation)
52 | : base(tableName, key, externalKey, tableSchema, tableAbbreviation, "INNER JOIN")
53 | {
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Attributes/Joins/JoinAttributeBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using MicroOrm.Dapper.Repositories.Config;
3 |
4 | namespace MicroOrm.Dapper.Repositories.Attributes.Joins;
5 |
6 |
7 | ///
8 | /// Base JOIN for LEFT/INNER/RIGHT
9 | ///
10 | public abstract class JoinAttributeBase : Attribute
11 | {
12 |
13 | ///
14 | /// Constructor
15 | ///
16 | protected JoinAttributeBase()
17 | {
18 | }
19 |
20 |
21 | ///
22 | /// Constructor
23 | ///
24 | protected JoinAttributeBase(string tableName, string key, string externalKey, string tableSchema, string tableAlias,
25 | string attrString = "JOIN")
26 | {
27 | TableName = MicroOrmConfig.TablePrefix + tableName;
28 | Key = key;
29 | ExternalKey = externalKey;
30 | TableSchema = tableSchema;
31 | TableAlias = tableAlias;
32 | JoinAttribute = attrString;
33 | }
34 |
35 | ///
36 | /// Join attribute string
37 | ///
38 | private string? JoinAttribute { get; }
39 |
40 | ///
41 | /// Name of external table
42 | ///
43 | public string? TableName { get; set; }
44 |
45 | ///
46 | /// Name of external table schema
47 | ///
48 | public string? TableSchema { get; set; }
49 |
50 | ///
51 | /// ForeignKey of this table
52 | ///
53 | public string? Key { get; set; }
54 |
55 | ///
56 | /// Key of external table
57 | ///
58 | public string? ExternalKey { get; set; }
59 |
60 | ///
61 | /// Table abbreviation override
62 | ///
63 | public string? TableAlias { get; set; }
64 |
65 | ///
66 | /// Convert to string
67 | ///
68 | ///
69 | public override string? ToString()
70 | {
71 | return JoinAttribute;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Attributes/Joins/LeftJoinAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace MicroOrm.Dapper.Repositories.Attributes.Joins;
2 |
3 |
4 | ///
5 | /// Generate LEFT JOIN
6 | ///
7 | public sealed class LeftJoinAttribute : JoinAttributeBase
8 | {
9 |
10 | ///
11 | /// Constructor
12 | ///
13 | public LeftJoinAttribute()
14 | {
15 | }
16 |
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Name of external table
22 | /// ForeignKey of this table
23 | /// Key of external table
24 | public LeftJoinAttribute(string tableName, string key, string externalKey)
25 | : base(tableName, key, externalKey, string.Empty, string.Empty, "LEFT JOIN")
26 | {
27 | }
28 |
29 |
30 | ///
31 | /// Constructor
32 | ///
33 | /// Name of external table
34 | /// ForeignKey of this table
35 | /// Key of external table
36 | /// Name of external table schema
37 | public LeftJoinAttribute(string tableName, string key, string externalKey, string tableSchema)
38 | : base(tableName, key, externalKey, tableSchema, string.Empty, "LEFT JOIN")
39 | {
40 | }
41 |
42 |
43 | ///
44 | /// Constructor
45 | ///
46 | /// Name of external table
47 | /// ForeignKey of this table
48 | /// Key of external table
49 | /// Name of external table schema
50 | /// External table alias
51 | public LeftJoinAttribute(string tableName, string key, string externalKey, string tableSchema, string tableAbbreviation)
52 | : base(tableName, key, externalKey, tableSchema, tableAbbreviation, "LEFT JOIN")
53 | {
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Attributes/Joins/RightJoinAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace MicroOrm.Dapper.Repositories.Attributes.Joins;
2 |
3 |
4 | ///
5 | /// Generate RIGHT JOIN
6 | ///
7 | public sealed class RightJoinAttribute : JoinAttributeBase
8 | {
9 |
10 | ///
11 | /// Constructor
12 | ///
13 | public RightJoinAttribute()
14 | {
15 | }
16 |
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Name of external table
22 | /// ForeignKey of this table
23 | /// Key of external table
24 | public RightJoinAttribute(string tableName, string key, string externalKey)
25 | : base(tableName, key, externalKey, string.Empty, string.Empty, "RIGHT JOIN")
26 | {
27 | }
28 |
29 |
30 | ///
31 | /// Constructor
32 | ///
33 | /// Name of external table
34 | /// ForeignKey of this table
35 | /// Key of external table
36 | /// Name of external table schema
37 | public RightJoinAttribute(string tableName, string key, string externalKey, string tableSchema)
38 | : base(tableName, key, externalKey, tableSchema, string.Empty, "RIGHT JOIN")
39 | {
40 | }
41 |
42 |
43 | ///
44 | /// Constructor
45 | ///
46 | /// Name of external table
47 | /// ForeignKey of this table
48 | /// Key of external table
49 | /// Name of external table schema
50 | /// External table alias
51 | public RightJoinAttribute(string tableName, string key, string externalKey, string tableSchema, string tableAbbreviation)
52 | : base(tableName, key, externalKey, tableSchema, tableAbbreviation, "RIGHT JOIN")
53 | {
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Attributes/LogicalDelete/DeletedAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Attributes.LogicalDelete;
4 |
5 |
6 | ///
7 | /// Use with "Status" for logical delete
8 | ///
9 | public sealed class DeletedAttribute : Attribute
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/src/Attributes/LogicalDelete/StatusAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Attributes.LogicalDelete;
4 |
5 |
6 | ///
7 | /// Use with "Deleted" for logical delete
8 | ///
9 | public sealed class StatusAttribute : Attribute
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/src/Attributes/UpdatedAtAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Attributes;
4 |
5 |
6 | ///
7 | /// UpdatedAt. Warning!!! Changes the property during SQL generation
8 | ///
9 | public sealed class UpdatedAtAttribute : Attribute
10 | {
11 | ///
12 | /// [UpdatedAt] Attribute
13 | ///
14 | public UpdatedAtAttribute()
15 | {
16 | TimeKind = DateTimeKind.Utc;
17 | OffSet = 0;
18 | }
19 |
20 | ///
21 | /// The timezone offset
22 | ///
23 | public int OffSet { get; set; }
24 |
25 | ///
26 | /// Specified time kind, default UTC.
27 | ///
28 | public DateTimeKind TimeKind { get; set; }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Config/MicroOrmConfig.cs:
--------------------------------------------------------------------------------
1 | using MicroOrm.Dapper.Repositories.SqlGenerator;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Config;
4 |
5 | ///
6 | /// This class is used to support dependency injection
7 | ///
8 | public static class MicroOrmConfig
9 | {
10 | ///
11 | /// Type Sql provider
12 | ///
13 | public static SqlProvider SqlProvider { get; set; }
14 |
15 | ///
16 | /// Use quotation marks for TableName and ColumnName
17 | ///
18 | public static bool UseQuotationMarks { get; set; }
19 |
20 | ///
21 | /// Prefix for tables
22 | ///
23 | public static string? TablePrefix { get; set; }
24 |
25 | ///
26 | /// Allow Key attribute as Identity if Identity is not set
27 | ///
28 | public static bool AllowKeyAsIdentity { get; set; }
29 | }
30 |
--------------------------------------------------------------------------------
/src/DapperRepository.BulkInsert.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Dapper;
8 | using MicroOrm.Dapper.Repositories.SqlGenerator;
9 |
10 | namespace MicroOrm.Dapper.Repositories;
11 |
12 | ///
13 | /// Base Repository
14 | ///
15 | public partial class DapperRepository
16 | where TEntity : class
17 | {
18 |
19 | public virtual int BulkInsert(IEnumerable instances)
20 | {
21 | return BulkInsert(instances, null);
22 | }
23 |
24 |
25 | public virtual Task BulkInsertAsync(IEnumerable instances)
26 | {
27 | return BulkInsertAsync(instances, null, CancellationToken.None);
28 | }
29 |
30 |
31 | public virtual Task BulkInsertAsync(IEnumerable instances, CancellationToken cancellationToken)
32 | {
33 | return BulkInsertAsync(instances, null, cancellationToken);
34 | }
35 |
36 |
37 | public virtual int BulkInsert(IEnumerable instances, IDbTransaction? transaction)
38 | {
39 | int totalInstances = instances.Count();
40 | if(totalInstances == 0)
41 | return 0;
42 |
43 | if (SqlGenerator.Provider == SqlProvider.MSSQL)
44 | {
45 | var count = 0;
46 | var properties =
47 | (SqlGenerator.IsIdentity
48 | ? SqlGenerator.SqlProperties.Where(p => !p.PropertyName.Equals(SqlGenerator.IdentitySqlProperty.PropertyName, StringComparison.OrdinalIgnoreCase))
49 | : SqlGenerator.SqlProperties).ToList();
50 |
51 | var exceededTimes = (int)Math.Ceiling(totalInstances * properties.Count / 2099d);
52 | if (exceededTimes > 1)
53 | {
54 | var maxAllowedInstancesPerBatch = totalInstances / exceededTimes;
55 | if (maxAllowedInstancesPerBatch > 1000) maxAllowedInstancesPerBatch = 1000;
56 |
57 | var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
58 |
59 | for (var i = 0; i <= maxIterationCount; i++)
60 | {
61 | var skips = i * maxAllowedInstancesPerBatch;
62 |
63 | if (skips >= totalInstances)
64 | break;
65 |
66 | var items = instances.Skip(skips).Take(maxAllowedInstancesPerBatch);
67 | var msSqlQueryResult = SqlGenerator.GetBulkInsert(items);
68 | count += Connection.Execute(msSqlQueryResult.GetSql(), msSqlQueryResult.Param, transaction);
69 | }
70 |
71 | return count;
72 | }
73 | }
74 |
75 | var queryResult = SqlGenerator.GetBulkInsert(instances);
76 | return Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction);
77 | }
78 |
79 |
80 | public virtual Task BulkInsertAsync(IEnumerable instances, IDbTransaction? transaction)
81 | {
82 | return BulkInsertAsync(instances, transaction, CancellationToken.None);
83 | }
84 |
85 |
86 | public virtual async Task BulkInsertAsync(IEnumerable instances, IDbTransaction? transaction, CancellationToken cancellationToken)
87 | {
88 | if (SqlGenerator.Provider == SqlProvider.MSSQL)
89 | {
90 | var count = 0;
91 | var totalInstances = instances.Count();
92 |
93 | var properties =
94 | (SqlGenerator.IsIdentity
95 | ? SqlGenerator.SqlProperties.Where(p => !p.PropertyName.Equals(SqlGenerator.IdentitySqlProperty.PropertyName, StringComparison.OrdinalIgnoreCase))
96 | : SqlGenerator.SqlProperties).ToList();
97 |
98 | var exceededTimes = (int)Math.Ceiling(totalInstances * properties.Count / 2099d);
99 | if (exceededTimes > 1)
100 | {
101 | var maxAllowedInstancesPerBatch = totalInstances / exceededTimes;
102 | if (maxAllowedInstancesPerBatch > 1000) maxAllowedInstancesPerBatch = 1000;
103 |
104 | var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
105 |
106 | for (var i = 0; i <= maxIterationCount; i++)
107 | {
108 | var skips = i * maxAllowedInstancesPerBatch;
109 |
110 | if (skips >= totalInstances)
111 | break;
112 |
113 | var items = instances.Skip(i * maxAllowedInstancesPerBatch).Take(maxAllowedInstancesPerBatch);
114 | var msSqlQueryResult = SqlGenerator.GetBulkInsert(items);
115 | count += await Connection.ExecuteAsync(new CommandDefinition(msSqlQueryResult.GetSql(), msSqlQueryResult.Param, transaction,
116 | cancellationToken: cancellationToken)).ConfigureAwait(false);
117 | }
118 |
119 | return count;
120 | }
121 | }
122 |
123 | var queryResult = SqlGenerator.GetBulkInsert(instances);
124 | return await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken))
125 | .ConfigureAwait(false);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/DapperRepository.BulkUpdate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Dapper;
8 | using MicroOrm.Dapper.Repositories.SqlGenerator;
9 |
10 | namespace MicroOrm.Dapper.Repositories;
11 |
12 | ///
13 | /// Base Repository
14 | ///
15 | public partial class DapperRepository
16 | where TEntity : class
17 | {
18 |
19 | public virtual bool BulkUpdate(IEnumerable instances)
20 | {
21 | return BulkUpdate(instances, null);
22 | }
23 |
24 |
25 | public virtual bool BulkUpdate(IEnumerable instances, IDbTransaction? transaction)
26 | {
27 | int totalInstances = instances.Count();
28 | if(totalInstances == 0)
29 | return true;
30 |
31 | if (SqlGenerator.Provider == SqlProvider.MSSQL)
32 | {
33 | int count = 0;
34 | var properties = SqlGenerator.SqlProperties.ToList();
35 |
36 | int exceededTimes = (int)Math.Ceiling(totalInstances * properties.Count / 2099d);
37 | if (exceededTimes > 1)
38 | {
39 | int maxAllowedInstancesPerBatch = totalInstances / exceededTimes;
40 | if (maxAllowedInstancesPerBatch > 1000) maxAllowedInstancesPerBatch = 1000;
41 | var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
42 | for (int i = 0; i <= maxIterationCount; i++)
43 | {
44 | var skips = i * maxAllowedInstancesPerBatch;
45 |
46 | if (skips >= totalInstances)
47 | break;
48 |
49 | var items = instances.Skip(skips).Take(maxAllowedInstancesPerBatch);
50 | var msSqlQueryResult = SqlGenerator.GetBulkUpdate(items);
51 | count += Connection.Execute(msSqlQueryResult.GetSql(), msSqlQueryResult.Param, transaction);
52 | }
53 |
54 | return count > 0;
55 | }
56 | }
57 |
58 | var queryResult = SqlGenerator.GetBulkUpdate(instances);
59 | var result = Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction) > 0;
60 | return result;
61 | }
62 |
63 |
64 | public virtual Task BulkUpdateAsync(IEnumerable instances)
65 | {
66 | return BulkUpdateAsync(instances, null, CancellationToken.None);
67 | }
68 |
69 |
70 | public virtual Task BulkUpdateAsync(IEnumerable instances, CancellationToken cancellationToken)
71 | {
72 | return BulkUpdateAsync(instances, null, cancellationToken);
73 | }
74 |
75 |
76 | public virtual Task BulkUpdateAsync(IEnumerable instances, IDbTransaction? transaction)
77 | {
78 | return BulkUpdateAsync(instances, transaction, CancellationToken.None);
79 | }
80 |
81 |
82 | public virtual async Task BulkUpdateAsync(IEnumerable instances, IDbTransaction? transaction, CancellationToken cancellationToken)
83 | {
84 | if (SqlGenerator.Provider == SqlProvider.MSSQL)
85 | {
86 | int count = 0;
87 | int totalInstances = instances.Count();
88 |
89 | var properties = SqlGenerator.SqlProperties.ToList();
90 |
91 | int exceededTimes = (int)Math.Ceiling(totalInstances * properties.Count / 2099d);
92 | if (exceededTimes > 1)
93 | {
94 | int maxAllowedInstancesPerBatch = totalInstances / exceededTimes;
95 | if (maxAllowedInstancesPerBatch > 1000) maxAllowedInstancesPerBatch = 1000;
96 |
97 | var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
98 |
99 | for (var i = 0; i <= maxIterationCount; i++)
100 | {
101 | var skips = i * maxAllowedInstancesPerBatch;
102 |
103 | if (skips >= totalInstances)
104 | break;
105 |
106 | var items = instances.Skip(skips).Take(maxAllowedInstancesPerBatch);
107 | var msSqlQueryResult = SqlGenerator.GetBulkUpdate(items);
108 | count += await Connection.ExecuteAsync(new CommandDefinition(msSqlQueryResult.GetSql(), msSqlQueryResult.Param, transaction,
109 | cancellationToken: cancellationToken)).ConfigureAwait(false);
110 | }
111 |
112 | return count > 0;
113 | }
114 | }
115 |
116 | var queryResult = SqlGenerator.GetBulkUpdate(instances);
117 | var result = await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
118 | return result;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/DapperRepository.Delete.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq.Expressions;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Dapper;
7 |
8 | namespace MicroOrm.Dapper.Repositories;
9 |
10 | ///
11 | /// Base Repository
12 | ///
13 | public partial class DapperRepository
14 | where TEntity : class
15 | {
16 |
17 | public virtual bool Delete(TEntity instance)
18 | {
19 | return Delete(instance, null, null);
20 | }
21 |
22 |
23 | public virtual bool Delete(TEntity instance, TimeSpan? timeout)
24 | {
25 | return Delete(instance, null, timeout);
26 | }
27 |
28 |
29 | public virtual bool Delete(TEntity instance, IDbTransaction? transaction, TimeSpan? timeout)
30 | {
31 | var queryResult = SqlGenerator.GetDelete(instance);
32 | int? commandTimeout = null;
33 | if (timeout.HasValue)
34 | commandTimeout = timeout.Value.Seconds;
35 | var deleted = Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction, commandTimeout) > 0;
36 | return deleted;
37 | }
38 |
39 |
40 | public virtual bool Delete(Expression>? predicate)
41 | {
42 | return Delete(predicate, null, null);
43 | }
44 |
45 |
46 | public virtual bool Delete(Expression>? predicate, TimeSpan? timeout)
47 | {
48 | return Delete(predicate, null, timeout);
49 | }
50 |
51 |
52 | public virtual bool Delete(Expression>? predicate, IDbTransaction? transaction, TimeSpan? timeout)
53 | {
54 | var queryResult = SqlGenerator.GetDelete(predicate);
55 | int? commandTimeout = null;
56 | if (timeout.HasValue)
57 | commandTimeout = timeout.Value.Seconds;
58 | var deleted = Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction, commandTimeout) > 0;
59 | return deleted;
60 | }
61 |
62 |
63 | public virtual Task DeleteAsync(TEntity instance, CancellationToken cancellationToken = default)
64 | {
65 | return DeleteAsync(instance, null, null, cancellationToken);
66 | }
67 |
68 |
69 | public virtual Task DeleteAsync(TEntity instance, TimeSpan? timeout, CancellationToken cancellationToken = default)
70 | {
71 | return DeleteAsync(instance, null, timeout, cancellationToken);
72 | }
73 |
74 |
75 |
76 | public virtual async Task DeleteAsync(TEntity instance, IDbTransaction? transaction, TimeSpan? timeout, CancellationToken cancellationToken = default)
77 | {
78 | var queryResult = SqlGenerator.GetDelete(instance);
79 | int? commandTimeout = null;
80 | if (timeout.HasValue)
81 | commandTimeout = timeout.Value.Seconds;
82 | var deleted = await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, commandTimeout,
83 | cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
84 | return deleted;
85 | }
86 |
87 |
88 | public virtual Task DeleteAsync(Expression>? predicate, CancellationToken cancellationToken = default)
89 | {
90 | return DeleteAsync(predicate, null, null, cancellationToken);
91 | }
92 |
93 |
94 | public virtual Task DeleteAsync(Expression>? predicate, TimeSpan? timeout, CancellationToken cancellationToken = default)
95 | {
96 | return DeleteAsync(predicate, null, timeout, cancellationToken);
97 | }
98 |
99 |
100 |
101 | public virtual async Task DeleteAsync(Expression>? predicate, IDbTransaction? transaction, TimeSpan? timeout,
102 | CancellationToken cancellationToken = default)
103 | {
104 | var queryResult = SqlGenerator.GetDelete(predicate);
105 | int? commandTimeout = null;
106 | if (timeout.HasValue)
107 | commandTimeout = timeout.Value.Seconds;
108 | var deleted = await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, commandTimeout,
109 | cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
110 | return deleted;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/DapperRepository.Insert.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Dapper;
7 |
8 | namespace MicroOrm.Dapper.Repositories;
9 |
10 | ///
11 | /// Base Repository
12 | ///
13 | public partial class DapperRepository
14 | where TEntity : class
15 | {
16 |
17 | public virtual bool Insert(TEntity instance)
18 | {
19 | return Insert(instance, null);
20 | }
21 |
22 |
23 | public virtual Task InsertAsync(TEntity instance)
24 | {
25 | return InsertAsync(instance, null, CancellationToken.None);
26 | }
27 |
28 |
29 | public virtual Task InsertAsync(TEntity instance, CancellationToken cancellationToken)
30 | {
31 | return InsertAsync(instance, null, cancellationToken);
32 | }
33 |
34 |
35 | public virtual bool Insert(TEntity instance, IDbTransaction? transaction)
36 | {
37 | var queryResult = SqlGenerator.GetInsert(instance);
38 | if (SqlGenerator.IsIdentity)
39 | {
40 | if (SqlGenerator.Provider == Repositories.SqlGenerator.SqlProvider.Oracle)
41 | {
42 | Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction);
43 | int newId = ((DynamicParameters)(queryResult.Param!)).Get(":newId");
44 | return SetValue(newId, instance);
45 | }
46 | else
47 | {
48 | var newId = Connection.Query(queryResult.GetSql(), queryResult.Param, transaction).FirstOrDefault();
49 | return SetValue(newId, instance);
50 | }
51 | }
52 |
53 | return Connection.Execute(queryResult.GetSql(), instance, transaction) > 0;
54 | }
55 |
56 |
57 | public virtual Task InsertAsync(TEntity instance, IDbTransaction? transaction)
58 | {
59 | return InsertAsync(instance, transaction, CancellationToken.None);
60 | }
61 |
62 |
63 | public virtual async Task InsertAsync(TEntity instance, IDbTransaction? transaction, CancellationToken cancellationToken)
64 | {
65 | var queryResult = SqlGenerator.GetInsert(instance);
66 | if (SqlGenerator.IsIdentity)
67 | {
68 | if (SqlGenerator.Provider == Repositories.SqlGenerator.SqlProvider.Oracle)
69 | {
70 | await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false);
71 | int newId = ((DynamicParameters)(queryResult.Param!)).Get(":newId");
72 | return SetValue(newId, instance);
73 | }
74 | else
75 | {
76 | var newId = (await Connection.QueryAsync(queryResult.GetSql(), queryResult.Param, transaction).ConfigureAwait(false)).FirstOrDefault();
77 | return SetValue(newId, instance);
78 | }
79 | }
80 |
81 | return await Connection.ExecuteAsync(new CommandDefinition(queryResult.GetSql(), instance, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
82 | }
83 |
84 | private bool SetValue(long newId, TEntity instance)
85 | {
86 | var added = newId > 0;
87 | if (added && SqlGenerator.IsIdentity)
88 | {
89 | var newParsedId = Convert.ChangeType(newId, SqlGenerator.IdentitySqlProperty.PropertyInfo.PropertyType);
90 | SqlGenerator.IdentitySqlProperty.PropertyInfo.SetValue(instance, newParsedId);
91 | }
92 |
93 | return added;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/DapperRepository.Update.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq.Expressions;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Dapper;
7 |
8 | namespace MicroOrm.Dapper.Repositories;
9 |
10 | ///
11 | /// Base Repository
12 | ///
13 | public partial class DapperRepository
14 | where TEntity : class
15 | {
16 |
17 | public virtual bool Update(TEntity instance, params Expression>[] includes)
18 | {
19 | return Update(instance, null, includes);
20 | }
21 |
22 |
23 | public virtual bool Update(TEntity instance, IDbTransaction? transaction, params Expression>[] includes)
24 | {
25 | var sqlQuery = SqlGenerator.GetUpdate(instance, includes);
26 | var updated = Connection.Execute(sqlQuery.GetSql(), sqlQuery.Param, transaction) > 0;
27 | return updated;
28 | }
29 |
30 |
31 | public virtual Task UpdateAsync(TEntity instance, params Expression>[] includes)
32 | {
33 | return UpdateAsync(instance, null, CancellationToken.None, includes);
34 | }
35 |
36 |
37 | public virtual Task UpdateAsync(TEntity instance, CancellationToken cancellationToken, params Expression>[] includes)
38 | {
39 | return UpdateAsync(instance, null, cancellationToken, includes);
40 | }
41 |
42 |
43 | public virtual Task UpdateAsync(TEntity instance, IDbTransaction? transaction, params Expression>[] includes)
44 | {
45 | return UpdateAsync(instance, transaction, CancellationToken.None, includes);
46 | }
47 |
48 |
49 | public virtual async Task UpdateAsync(TEntity instance, IDbTransaction? transaction, CancellationToken cancellationToken,
50 | params Expression>[] includes)
51 | {
52 | var sqlQuery = SqlGenerator.GetUpdate(instance, includes);
53 | var updated = await Connection.ExecuteAsync(new CommandDefinition(sqlQuery.GetSql(), sqlQuery.Param, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
54 | return updated;
55 | }
56 |
57 |
58 | public virtual bool Update(Expression>? predicate, TEntity instance, params Expression>[] includes)
59 | {
60 | return Update(predicate, instance, null, includes);
61 | }
62 |
63 |
64 | public virtual Task UpdateAsync(Expression>? predicate, TEntity instance, params Expression>[] includes)
65 | {
66 | return UpdateAsync(predicate, instance, CancellationToken.None, includes);
67 | }
68 |
69 |
70 | public virtual bool Update(Expression>? predicate, TEntity instance, IDbTransaction? transaction, params Expression>[] includes)
71 | {
72 | var sqlQuery = SqlGenerator.GetUpdate(predicate, instance, includes);
73 | var updated = Connection.Execute(sqlQuery.GetSql(), sqlQuery.Param, transaction) > 0;
74 | return updated;
75 | }
76 |
77 |
78 | public virtual Task UpdateAsync(Expression>? predicate, TEntity instance, CancellationToken cancellationToken, params Expression>[] includes)
79 | {
80 | return UpdateAsync(predicate, instance, null, cancellationToken, includes);
81 | }
82 |
83 |
84 | public virtual Task UpdateAsync(Expression>? predicate, TEntity instance, IDbTransaction? transaction, params Expression>[] includes)
85 | {
86 | return UpdateAsync(predicate, instance, transaction, CancellationToken.None, includes);
87 | }
88 |
89 |
90 | public virtual async Task UpdateAsync(Expression>? predicate, TEntity instance, IDbTransaction? transaction,
91 | CancellationToken cancellationToken,
92 | params Expression>[] includes)
93 | {
94 | var sqlQuery = SqlGenerator.GetUpdate(predicate, instance, includes);
95 | var updated = await Connection.ExecuteAsync(new CommandDefinition(sqlQuery.GetSql(), sqlQuery.Param, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false) > 0;
96 | return updated;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/DapperRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using MicroOrm.Dapper.Repositories.SqlGenerator;
3 |
4 | namespace MicroOrm.Dapper.Repositories;
5 |
6 | ///
7 | /// Base Repository
8 | ///
9 | public partial class DapperRepository : ReadOnlyDapperRepository, IDapperRepository
10 | where TEntity : class
11 | {
12 | ///
13 | /// Constructor
14 | ///
15 | public DapperRepository(IDbConnection connection)
16 | : base(connection)
17 | {
18 | }
19 |
20 | ///
21 | /// Constructor
22 | ///
23 | public DapperRepository(IDbConnection connection, ISqlGenerator sqlGenerator)
24 | : base(connection, sqlGenerator)
25 | {
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DbContext/DapperDbContext.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.Common;
3 | using System.Threading.Tasks;
4 |
5 | namespace MicroOrm.Dapper.Repositories.DbContext;
6 |
7 | public class DapperDbContext : IDapperDbContext
8 | {
9 | ///
10 | /// Internal DB connection instance
11 | ///
12 | protected readonly IDbConnection InnerConnection;
13 |
14 | ///
15 | /// Create new DB context with connection
16 | ///
17 | protected DapperDbContext(IDbConnection connection)
18 | {
19 | InnerConnection = connection;
20 | }
21 |
22 | public virtual IDbConnection Connection
23 | {
24 | get
25 | {
26 | OpenConnection();
27 | return InnerConnection;
28 | }
29 | }
30 |
31 | public void OpenConnection()
32 | {
33 | if (InnerConnection.State != ConnectionState.Open && InnerConnection.State != ConnectionState.Connecting)
34 | InnerConnection.Open();
35 | }
36 |
37 | public async Task OpenConnectionAsync()
38 | {
39 | if (InnerConnection.State != ConnectionState.Open && InnerConnection.State != ConnectionState.Connecting)
40 | {
41 | if (InnerConnection is DbConnection dbConnection)
42 | await dbConnection.OpenAsync().ConfigureAwait(false);
43 | else
44 | InnerConnection.Open();
45 | }
46 | }
47 |
48 | public virtual IDbTransaction BeginTransaction()
49 | {
50 | return Connection.BeginTransaction();
51 | }
52 |
53 | public virtual async Task BeginTransactionAsync()
54 | {
55 | if (InnerConnection is DbConnection dbConnection)
56 | {
57 | await OpenConnectionAsync().ConfigureAwait(false);
58 | #if NETCOREAPP3_0_OR_GREATER
59 | return await dbConnection.BeginTransactionAsync().ConfigureAwait(false);
60 | #else
61 | return dbConnection.BeginTransaction();
62 | #endif
63 | }
64 |
65 | return BeginTransaction();
66 | }
67 |
68 | ///
69 | /// Close DB connection
70 | ///
71 | public void Dispose()
72 | {
73 | if (InnerConnection.State != ConnectionState.Closed)
74 | InnerConnection.Close();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/DbContext/IDapperDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Threading.Tasks;
4 |
5 | namespace MicroOrm.Dapper.Repositories.DbContext;
6 |
7 | ///
8 | /// Wrapper for database connection management
9 | ///
10 | public interface IDapperDbContext : IDisposable
11 | {
12 | ///
13 | /// Get DB Connection, open connection if necessary
14 | ///
15 | IDbConnection Connection { get; }
16 |
17 | ///
18 | /// Open DB connection if not already open
19 | ///
20 | void OpenConnection();
21 |
22 | ///
23 | /// Open DB connection asynchronously if not already open
24 | ///
25 | Task OpenConnectionAsync();
26 |
27 | ///
28 | /// Begin transaction, open connection if necessary
29 | ///
30 | IDbTransaction BeginTransaction();
31 |
32 | ///
33 | /// Begin transaction asynchronously, open connection if necessary
34 | ///
35 | Task BeginTransactionAsync();
36 | }
37 |
--------------------------------------------------------------------------------
/src/Extensions/CollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace MicroOrm.Dapper.Repositories.Extensions;
4 |
5 | internal static class CollectionExtensions
6 | {
7 | ///
8 | /// AddRange ICollection
9 | ///
10 | ///
11 | ///
12 | public static void AddRange(this ICollection collection, IEnumerable addCollection)
13 | {
14 | if (collection == null || addCollection == null)
15 | return;
16 |
17 | foreach (var item in addCollection)
18 | {
19 | collection.Add(item);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Extensions/OracleDynamicParametersExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using Dapper;
3 |
4 | namespace MicroOrm.Dapper.Repositories.Extensions;
5 |
6 | ///
7 | /// Currently it only add output parameter with type DbType.Int32.
8 | /// It should actually check the prima key type then mapping it to different DbType such as DbType.Int64, etc.
9 | /// If GUID support is added, it should also be added here.
10 | ///
11 | internal static class OracleDynamicParametersExtensions
12 | {
13 | public static void AddOracleOutputParameterForId(this DynamicParameters param)
14 | {
15 | param.Add(name: "newId", dbType: DbType.Int32, direction: ParameterDirection.Output);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Extensions/TypeExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.ComponentModel.DataAnnotations.Schema;
5 | using System.Linq;
6 | using System.Reflection;
7 | using MicroOrm.Dapper.Repositories.Attributes;
8 | using MicroOrm.Dapper.Repositories.SqlGenerator;
9 |
10 | namespace MicroOrm.Dapper.Repositories.Extensions;
11 |
12 | internal static class TypeExtensions
13 | {
14 | private static readonly ConcurrentDictionary _reflectionPropertyCache = new ConcurrentDictionary();
15 | private static readonly ConcurrentDictionary _reflectionPrimitivePropertyCache = new ConcurrentDictionary();
16 | private static readonly ConcurrentDictionary _metaDataPropertyCache = new ConcurrentDictionary();
17 |
18 | public static PropertyInfo[] FindClassProperties(this Type objectType)
19 | {
20 | if (_reflectionPropertyCache.TryGetValue(objectType, out var cachedEntry))
21 | return cachedEntry;
22 |
23 | var propertyInfos = objectType.GetProperties()
24 | .OrderByDescending(x => x.GetCustomAttribute() != null)
25 | .ThenByDescending(x => x.GetCustomAttribute() != null)
26 | .ThenBy(p => p.GetCustomAttributes()
27 | .Select(a => a.Order)
28 | .DefaultIfEmpty(int.MaxValue)
29 | .FirstOrDefault()).ToArray();
30 |
31 | _reflectionPropertyCache.TryAdd(objectType, propertyInfos);
32 |
33 | return propertyInfos;
34 | }
35 |
36 | public static PropertyInfo[] FindClassPrimitiveProperties(this Type objectType)
37 | {
38 | if (_reflectionPrimitivePropertyCache.TryGetValue(objectType, out var cachedEntry))
39 | return cachedEntry;
40 |
41 | var props = objectType.GetProperties();
42 | var propertyInfos = props
43 | .OrderByDescending(x => x.GetCustomAttribute() != null)
44 | .ThenByDescending(x => x.GetCustomAttribute() != null)
45 | .ThenBy(p => p.GetCustomAttributes()
46 | .Select(a => a.Order)
47 | .DefaultIfEmpty(int.MaxValue)
48 | .FirstOrDefault()).Where(ExpressionHelper.GetPrimitivePropertiesPredicate()).ToArray();
49 |
50 | _reflectionPrimitivePropertyCache.TryAdd(objectType, propertyInfos);
51 |
52 | return propertyInfos;
53 | }
54 |
55 | public static SqlPropertyMetadata[] FindClassMetaDataProperties(this Type objectType)
56 | {
57 | if (_metaDataPropertyCache.TryGetValue(objectType, out var cachedEntry))
58 | return cachedEntry;
59 |
60 | var props = objectType.GetProperties();
61 | var propertyInfos = props
62 | .OrderByDescending(x => x.GetCustomAttribute() != null)
63 | .ThenByDescending(x => x.GetCustomAttribute() != null)
64 | .ThenBy(p => p.GetCustomAttributes()
65 | .Select(a => a.Order)
66 | .DefaultIfEmpty(int.MaxValue)
67 | .FirstOrDefault()).Where(ExpressionHelper.GetPrimitivePropertiesPredicate())
68 | .Where(p => !p.GetCustomAttributes().Any()).Select(p => new SqlPropertyMetadata(p)).ToArray();
69 |
70 | _metaDataPropertyCache.TryAdd(objectType, propertyInfos);
71 |
72 | return propertyInfos;
73 | }
74 |
75 | public static Type UnwrapNullableType(this Type type) => Nullable.GetUnderlyingType(type) ?? type;
76 | }
77 |
--------------------------------------------------------------------------------
/src/MicroOrm.Dapper.Repositories.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | CRUD for Dapper
4 | 2015 © Serge K
5 | Serge K and Contributors
6 | net462;netstandard2.0;net8.0
7 | enable
8 | true
9 | true
10 | MicroOrm.Dapper.Repositories
11 | dapper;micro-orm;repositories;crud
12 | icon.png
13 | README.md
14 | MIT
15 | git
16 | https://github.com/phnx47/dapper-repositories
17 | true
18 | true
19 | snupkg
20 | true
21 | nupkgs
22 | true
23 | true
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.Count.Join.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq.Expressions;
4 | using System.Threading.Tasks;
5 | using Dapper;
6 |
7 | namespace MicroOrm.Dapper.Repositories;
8 |
9 |
10 | ///
11 | /// Base Repository
12 | ///
13 | public partial class ReadOnlyDapperRepository
14 | where TEntity : class
15 | {
16 |
17 | public virtual int Count(params Expression>[] includes)
18 | {
19 | return Count(null, transaction: null);
20 | }
21 |
22 |
23 | public virtual int Count(IDbTransaction? transaction, params Expression>[] includes)
24 | {
25 | return Count(null, transaction, includes: includes);
26 | }
27 |
28 |
29 | public virtual int Count(Expression>? predicate, params Expression>[] includes)
30 | {
31 | return Count(predicate, transaction: null, includes: includes);
32 | }
33 |
34 |
35 | public virtual int Count(Expression>? predicate, IDbTransaction? transaction, params Expression>[] includes)
36 | {
37 | var queryResult = SqlGenerator.GetCount(predicate, includes);
38 | return Connection.QueryFirstOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
39 | }
40 |
41 |
42 | public virtual int Count(Expression> distinctField, params Expression>[] includes)
43 | {
44 | return Count(distinctField, null, includes: includes);
45 | }
46 |
47 |
48 | public virtual int Count(Expression> distinctField, IDbTransaction? transaction, params Expression>[] includes)
49 | {
50 | return Count(null, distinctField, transaction);
51 | }
52 |
53 |
54 | public virtual int Count(Expression>? predicate, Expression> distinctField, params Expression>[] includes)
55 | {
56 | return Count(predicate, distinctField, null, includes);
57 | }
58 |
59 |
60 | public virtual int Count(Expression>? predicate, Expression> distinctField, IDbTransaction? transaction,
61 | params Expression>[] includes)
62 | {
63 | var queryResult = SqlGenerator.GetCount(predicate, distinctField, includes);
64 | return Connection.QueryFirstOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
65 | }
66 |
67 |
68 | public virtual Task CountAsync(params Expression>[] includes)
69 | {
70 | return CountAsync(transaction: null, includes: includes);
71 | }
72 |
73 |
74 | public virtual Task CountAsync(IDbTransaction? transaction, params Expression>[] includes)
75 | {
76 | return CountAsync(null, transaction, includes: includes);
77 | }
78 |
79 |
80 | public virtual Task CountAsync(Expression>? predicate, params Expression>[] includes)
81 | {
82 | return CountAsync(predicate, transaction: null, includes: includes);
83 | }
84 |
85 |
86 | public virtual Task CountAsync(Expression>? predicate, IDbTransaction? transaction, params Expression>[] includes)
87 | {
88 | var queryResult = SqlGenerator.GetCount(predicate, includes);
89 | return Connection.QueryFirstOrDefaultAsync(queryResult.GetSql(), queryResult.Param, transaction);
90 | }
91 |
92 |
93 | public virtual Task CountAsync(Expression> distinctField, params Expression>[] includes)
94 | {
95 | return CountAsync(distinctField, null, includes: includes);
96 | }
97 |
98 |
99 | public virtual Task CountAsync(Expression> distinctField, IDbTransaction? transaction, params Expression>[] includes)
100 | {
101 | return CountAsync(null, distinctField, transaction, includes: includes);
102 | }
103 |
104 |
105 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField,
106 | params Expression>[] includes)
107 | {
108 | return CountAsync(predicate, distinctField, null, includes: includes);
109 | }
110 |
111 |
112 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField, IDbTransaction? transaction,
113 | params Expression>[] includes)
114 | {
115 | var queryResult = SqlGenerator.GetCount(predicate, distinctField, includes);
116 | return Connection.QueryFirstOrDefaultAsync(queryResult.GetSql(), queryResult.Param, transaction);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.Count.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq.Expressions;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Dapper;
7 |
8 | namespace MicroOrm.Dapper.Repositories;
9 |
10 |
11 | ///
12 | /// Base Repository
13 | ///
14 | public partial class ReadOnlyDapperRepository
15 | where TEntity : class
16 | {
17 |
18 | public virtual int Count()
19 | {
20 | return Count(null, transaction: null);
21 | }
22 |
23 |
24 | public virtual Task CountAsync()
25 | {
26 | return CountAsync(transaction: null, cancellationToken: default);
27 | }
28 |
29 |
30 | public virtual Task CountAsync(CancellationToken cancellationToken)
31 | {
32 | return CountAsync(transaction: null, cancellationToken: cancellationToken);
33 | }
34 |
35 |
36 | public virtual int Count(IDbTransaction transaction)
37 | {
38 | return Count(null, transaction);
39 | }
40 |
41 |
42 | public virtual Task CountAsync(IDbTransaction transaction)
43 | {
44 | return CountAsync(null, transaction, cancellationToken: default);
45 | }
46 |
47 |
48 | public virtual Task CountAsync(IDbTransaction? transaction, CancellationToken cancellationToken)
49 | {
50 | return CountAsync(null, transaction, cancellationToken: cancellationToken);
51 | }
52 |
53 |
54 | public virtual int Count(Expression> predicate)
55 | {
56 | return Count(predicate, transaction: null);
57 | }
58 |
59 |
60 | public virtual Task CountAsync(Expression> predicate)
61 | {
62 | return CountAsync(predicate, transaction: null, cancellationToken: default);
63 | }
64 |
65 |
66 | public virtual int Count(Expression>? predicate, IDbTransaction? transaction)
67 | {
68 | var queryResult = SqlGenerator.GetCount(predicate);
69 | return Connection.QueryFirstOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
70 | }
71 |
72 |
73 | public virtual Task CountAsync(Expression>? predicate, CancellationToken cancellationToken)
74 | {
75 | return CountAsync(predicate, transaction: null, cancellationToken: cancellationToken);
76 | }
77 |
78 |
79 | public virtual Task CountAsync(Expression>? predicate, IDbTransaction? transaction)
80 | {
81 | return CountAsync(predicate, transaction, cancellationToken: default);
82 | }
83 |
84 |
85 | public virtual Task CountAsync(Expression>? predicate, IDbTransaction? transaction, CancellationToken cancellationToken)
86 | {
87 | var queryResult = SqlGenerator.GetCount(predicate);
88 | return Connection.QueryFirstOrDefaultAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken));
89 | }
90 |
91 |
92 | public virtual int Count(Expression> distinctField)
93 | {
94 | return Count(distinctField, transaction: null);
95 | }
96 |
97 |
98 | public virtual Task CountAsync(Expression> distinctField)
99 | {
100 | return CountAsync(distinctField, transaction: null, cancellationToken: default);
101 | }
102 |
103 |
104 | public virtual Task CountAsync(Expression> distinctField, CancellationToken cancellationToken)
105 | {
106 | return CountAsync(distinctField, transaction: null, cancellationToken: cancellationToken);
107 | }
108 |
109 |
110 | public virtual int Count(Expression> distinctField, IDbTransaction? transaction)
111 | {
112 | return Count(null, distinctField, transaction);
113 | }
114 |
115 |
116 | public virtual Task CountAsync(Expression> distinctField, IDbTransaction? transaction)
117 | {
118 | return CountAsync(null, distinctField, transaction, cancellationToken: default);
119 | }
120 |
121 |
122 | public virtual Task CountAsync(Expression> distinctField, IDbTransaction? transaction, CancellationToken cancellationToken)
123 | {
124 | return CountAsync(null, distinctField, transaction, cancellationToken: cancellationToken);
125 | }
126 |
127 |
128 | public virtual int Count(Expression>? predicate, Expression> distinctField)
129 | {
130 | return Count(predicate, distinctField, transaction: null);
131 | }
132 |
133 |
134 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField)
135 | {
136 | return CountAsync(predicate, distinctField, transaction: null, cancellationToken: default);
137 | }
138 |
139 |
140 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField, CancellationToken cancellationToken)
141 | {
142 | return CountAsync(predicate, distinctField, transaction: null, cancellationToken: cancellationToken);
143 | }
144 |
145 |
146 | public virtual int Count(Expression>? predicate, Expression> distinctField, IDbTransaction? transaction)
147 | {
148 | var queryResult = SqlGenerator.GetCount(predicate, distinctField);
149 | return Connection.QueryFirstOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
150 | }
151 |
152 |
153 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField, IDbTransaction? transaction)
154 | {
155 | return CountAsync(predicate, distinctField, transaction, cancellationToken: default);
156 | }
157 |
158 |
159 | public virtual Task CountAsync(Expression>? predicate, Expression> distinctField, IDbTransaction? transaction, CancellationToken cancellationToken)
160 | {
161 | var queryResult = SqlGenerator.GetCount(predicate, distinctField);
162 | return Connection.QueryFirstOrDefaultAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken));
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.Find.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Linq.Expressions;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Dapper;
7 |
8 |
9 | namespace MicroOrm.Dapper.Repositories;
10 |
11 | ///
12 | /// Base Repository
13 | ///
14 | public partial class ReadOnlyDapperRepository
15 | where TEntity : class
16 | {
17 |
18 | public virtual TEntity? Find()
19 | {
20 | return Find(null, null);
21 | }
22 |
23 |
24 | public virtual Task FindAsync()
25 | {
26 | return FindAsync(null, null, cancellationToken: default);
27 | }
28 |
29 |
30 | public virtual Task FindAsync(CancellationToken cancellationToken)
31 | {
32 | return FindAsync(null, null, cancellationToken: cancellationToken);
33 | }
34 |
35 |
36 | public virtual TEntity? Find(IDbTransaction transaction)
37 | {
38 | return Find(null, transaction);
39 | }
40 |
41 |
42 | public virtual Task FindAsync(IDbTransaction transaction)
43 | {
44 | return FindAsync(null, transaction, cancellationToken: default);
45 | }
46 |
47 |
48 | public virtual Task FindAsync(IDbTransaction? transaction, CancellationToken cancellationToken)
49 | {
50 | return FindAsync(null, transaction, cancellationToken: cancellationToken);
51 | }
52 |
53 |
54 | public virtual TEntity? Find(Expression> predicate)
55 | {
56 | return Find(predicate, null);
57 | }
58 |
59 |
60 | public virtual Task FindAsync(Expression> predicate)
61 | {
62 | return FindAsync(predicate, null, cancellationToken: default);
63 | }
64 |
65 |
66 | public virtual Task FindAsync(Expression>? predicate, CancellationToken cancellationToken)
67 | {
68 | return FindAsync(predicate, null, cancellationToken: cancellationToken);
69 | }
70 |
71 |
72 | public virtual TEntity? Find(Expression>? predicate, IDbTransaction? transaction)
73 | {
74 | var queryResult = SqlGenerator.GetSelectFirst(predicate, FilterData);
75 | return Connection.QueryFirstOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
76 | }
77 |
78 |
79 | public virtual Task FindAsync(Expression>? predicate, IDbTransaction? transaction)
80 | {
81 | return FindAsync(predicate, transaction, cancellationToken: default);
82 | }
83 |
84 |
85 | public virtual Task FindAsync(Expression>? predicate, IDbTransaction? transaction, CancellationToken cancellationToken)
86 | {
87 | var queryResult = SqlGenerator.GetSelectFirst(predicate, FilterData);
88 | return Connection.QueryFirstOrDefaultAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken));
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.FindAll.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq.Expressions;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Dapper;
8 |
9 | namespace MicroOrm.Dapper.Repositories;
10 |
11 | ///
12 | /// Base Repository
13 | ///
14 | public partial class ReadOnlyDapperRepository
15 | where TEntity : class
16 | {
17 |
18 | public virtual IEnumerable FindAll()
19 | {
20 | return FindAll(null, transaction: null);
21 | }
22 |
23 |
24 | public virtual Task> FindAllAsync()
25 | {
26 | return FindAllAsync(null, transaction: null, cancellationToken: default);
27 | }
28 |
29 |
30 | public virtual Task> FindAllAsync(CancellationToken cancellationToken)
31 | {
32 | return FindAllAsync(null, transaction: null, cancellationToken: cancellationToken);
33 | }
34 |
35 |
36 | public virtual IEnumerable FindAll(IDbTransaction transaction)
37 | {
38 | return FindAll(null, transaction);
39 | }
40 |
41 |
42 | public virtual Task> FindAllAsync(IDbTransaction transaction)
43 | {
44 | return FindAllAsync(null, transaction, cancellationToken: default);
45 | }
46 |
47 |
48 | public virtual Task> FindAllAsync(IDbTransaction? transaction, CancellationToken cancellationToken)
49 | {
50 | return FindAllAsync(null, transaction, cancellationToken: cancellationToken);
51 | }
52 |
53 |
54 | public virtual IEnumerable FindAll(Expression> predicate)
55 | {
56 | return FindAll(predicate, transaction: null);
57 | }
58 |
59 |
60 | public virtual Task> FindAllAsync(Expression> predicate)
61 | {
62 | return FindAllAsync(predicate, transaction: null, cancellationToken: default);
63 | }
64 |
65 |
66 | public virtual Task> FindAllAsync(Expression>? predicate, CancellationToken cancellationToken)
67 | {
68 | return FindAllAsync(predicate, transaction: null, cancellationToken: cancellationToken);
69 | }
70 |
71 |
72 | public virtual IEnumerable FindAll(Expression>? predicate,
73 | Expression> orderBy)
74 | {
75 | return FindAll(predicate, transaction: null);
76 | }
77 |
78 |
79 | public virtual IEnumerable FindAll(Expression>? predicate, IDbTransaction? transaction)
80 | {
81 | var queryResult = SqlGenerator.GetSelectAll(predicate, FilterData);
82 | return Connection.Query(queryResult.GetSql(), queryResult.Param, transaction);
83 | }
84 |
85 |
86 | public virtual Task> FindAllAsync(Expression>? predicate, IDbTransaction? transaction)
87 | {
88 | return FindAllAsync(predicate, transaction, cancellationToken: default);
89 | }
90 |
91 |
92 | public virtual async Task> FindAllAsync(Expression>? predicate, IDbTransaction? transaction, CancellationToken cancellationToken)
93 | {
94 | var queryResult = SqlGenerator.GetSelectAll(predicate, FilterData);
95 | return await Connection.QueryAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken)).ConfigureAwait(false);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.FindById.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Dapper;
5 |
6 | namespace MicroOrm.Dapper.Repositories;
7 |
8 | ///
9 | /// Base Repository
10 | ///
11 | public partial class ReadOnlyDapperRepository
12 | where TEntity : class
13 | {
14 |
15 | public virtual TEntity? FindById(object id)
16 | {
17 | return FindById(id, null);
18 | }
19 |
20 |
21 | public virtual TEntity? FindById(object id, IDbTransaction? transaction)
22 | {
23 | var queryResult = SqlGenerator.GetSelectById(id, null);
24 | return Connection.QuerySingleOrDefault(queryResult.GetSql(), queryResult.Param, transaction);
25 | }
26 |
27 |
28 | public virtual Task FindByIdAsync(object id)
29 | {
30 | return FindByIdAsync(id, null, cancellationToken: default);
31 | }
32 |
33 |
34 | public virtual Task FindByIdAsync(object id, CancellationToken cancellationToken)
35 | {
36 | return FindByIdAsync(id, null, cancellationToken: cancellationToken);
37 | }
38 |
39 |
40 | public virtual Task FindByIdAsync(object id, IDbTransaction? transaction)
41 | {
42 | return FindByIdAsync(id, transaction, cancellationToken: default);
43 | }
44 |
45 |
46 | public virtual Task FindByIdAsync(object id, IDbTransaction? transaction, CancellationToken cancellationToken)
47 | {
48 | var queryResult = SqlGenerator.GetSelectById(id, null);
49 | return Connection.QuerySingleOrDefaultAsync(new CommandDefinition(queryResult.GetSql(), queryResult.Param, transaction, cancellationToken: cancellationToken));
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.SetGroupBy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using MicroOrm.Dapper.Repositories.SqlGenerator.Filters;
6 |
7 | namespace MicroOrm.Dapper.Repositories;
8 |
9 | ///
10 | /// Base Repository
11 | ///
12 | public partial class ReadOnlyDapperRepository
13 | where TEntity : class
14 | {
15 |
16 | public virtual IReadOnlyDapperRepository SetGroupBy()
17 | {
18 | FilterData.OrderInfo = null;
19 | return this;
20 | }
21 |
22 |
23 | public virtual IReadOnlyDapperRepository SetGroupBy(bool permanent,
24 | Expression> expr)
25 | {
26 | return SetGroupBy(permanent, expr);
27 | }
28 |
29 |
30 | public virtual IReadOnlyDapperRepository SetGroupBy(bool permanent,
31 | Expression> expr)
32 | {
33 | var order = FilterData.GroupInfo ?? new GroupInfo();
34 |
35 | var type = typeof(T);
36 | switch (expr.Body.NodeType)
37 | {
38 | case ExpressionType.Convert:
39 | {
40 | if (expr.Body is UnaryExpression { Operand: MemberExpression expression })
41 | {
42 | order.Columns = new List { GetProperty(expression, type) };
43 | }
44 |
45 | break;
46 | }
47 | case ExpressionType.MemberAccess:
48 | order.Columns = new List { GetProperty(expr.Body, type) };
49 | break;
50 | default:
51 | {
52 | var cols = (expr.Body as NewExpression)?.Arguments;
53 | var propertyNames = cols?.Select(expression => GetProperty(expression, type)).ToList();
54 | order.Columns = propertyNames;
55 | break;
56 | }
57 | }
58 |
59 | order.Permanent = permanent;
60 |
61 | FilterData.GroupInfo = order;
62 |
63 | return this;
64 | }
65 |
66 |
67 | public virtual IReadOnlyDapperRepository SetGroupBy(Expression> expr)
68 | {
69 | return SetGroupBy(false, expr);
70 | }
71 |
72 |
73 | public virtual IReadOnlyDapperRepository SetOrderBy(Expression> expr)
74 | {
75 | return SetGroupBy(false, expr);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.SetLimit.cs:
--------------------------------------------------------------------------------
1 | using MicroOrm.Dapper.Repositories.SqlGenerator.Filters;
2 |
3 | namespace MicroOrm.Dapper.Repositories;
4 |
5 | ///
6 | /// Base Repository
7 | ///
8 | public partial class ReadOnlyDapperRepository
9 | where TEntity : class
10 | {
11 |
12 | public virtual IReadOnlyDapperRepository SetLimit()
13 | {
14 | FilterData.LimitInfo = null;
15 | return this;
16 | }
17 |
18 |
19 | public virtual IReadOnlyDapperRepository SetLimit(uint limit, uint? offset, bool permanent)
20 | {
21 | if (limit <= 0)
22 | return this;
23 |
24 | var data = FilterData.LimitInfo ?? new LimitInfo();
25 | data.Limit = limit;
26 | data.Offset = offset;
27 | data.Permanent = permanent;
28 | FilterData.LimitInfo = data;
29 |
30 | return this;
31 | }
32 |
33 |
34 | public virtual IReadOnlyDapperRepository SetLimit(uint limit)
35 | {
36 | return SetLimit(limit, null, false);
37 | }
38 |
39 |
40 | public virtual IReadOnlyDapperRepository SetLimit(uint limit, uint offset)
41 | {
42 | return SetLimit(limit, offset, false);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/ReadOnlyDapperRepository.SetOrderBy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using MicroOrm.Dapper.Repositories.SqlGenerator.Filters;
6 |
7 | namespace MicroOrm.Dapper.Repositories;
8 |
9 | ///