├── .config
└── dotnet-tools.json
├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── pull-request.yml
│ └── release.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Directory.Packages.props
├── LICENSE
├── README.md
├── global.json
├── nuget.config
├── samples
├── .dockerignore
├── Context
│ ├── DataAccess
│ │ ├── BlogRepository.cs
│ │ ├── Configuration
│ │ │ ├── BlogCollectionConfiguration.cs
│ │ │ ├── TagCollectionConfiguration.cs
│ │ │ └── UserCollectionConfiguration.cs
│ │ ├── DataAccess.csproj
│ │ ├── IBlogRepository.cs
│ │ ├── ITagRepository.cs
│ │ ├── IUserRepository.cs
│ │ ├── ServiceCollectionExtensions.cs
│ │ ├── SimpleBlogDbContext.cs
│ │ ├── TagRepository.cs
│ │ ├── UserRepository.cs
│ │ └── WellKnown.cs
│ ├── Domain
│ │ ├── BlogService.cs
│ │ ├── Domain.csproj
│ │ ├── IBlogService.cs
│ │ ├── IUserService.cs
│ │ ├── ServiceCollectionExtensions.cs
│ │ └── UserService.cs
│ ├── Host
│ │ ├── Controllers
│ │ │ └── SimpleBlogController.cs
│ │ ├── Host.csproj
│ │ ├── Program.cs
│ │ ├── Properties
│ │ │ └── launchSettings.json
│ │ ├── Startup.cs
│ │ ├── appsettings.Development.json
│ │ └── appsettings.json
│ └── Models
│ │ ├── Blog.cs
│ │ ├── Models.csproj
│ │ ├── Tag.cs
│ │ └── User.cs
├── Directory.Packages.props
├── Migration
│ ├── Customer.cs
│ ├── ExampleMigration.cs
│ ├── Migration.csproj
│ ├── Program.cs
│ ├── Repository.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── MongoDB.Extensions.Samples.sln
└── src
├── Context.AllowedTypes.Tests
├── Context.AllowedTypes.Tests.csproj
├── Helpers
│ ├── Bar.cs
│ ├── Foo.cs
│ ├── MongoCollectionFixture.cs
│ └── TestHelpers.cs
├── MongoDatabaseBuilderTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── TypeObjectSerializerTests.cs
└── __snapshots__
│ ├── MongoDatabaseBuilderTests.AddAllowedTypes_AddAllowedTypesByNamespaces_Success.snap
│ ├── MongoDatabaseBuilderTests.AddAllowedTypes_AddAllowedTypesByTypes_Success.snap
│ ├── MongoDatabaseBuilderTests.AddAllowedTypes_AddAllowedTypesOfAllDependencies_Success.snap
│ ├── TypeObjectSerializerTests.AddAllowedTypes_AddAllowedTypesByNamespaces_Success.snap
│ ├── TypeObjectSerializerTests.AddAllowedTypes_AddAllowedTypesByTypes_Success.snap
│ ├── TypeObjectSerializerTests.AddAllowedTypes_AddAllowedTypesOfAllDependencies_Success.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_InAllowedNamespaces_True.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_InAllowedTypesInDependencies_True.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_InAllowedTypes_False.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_InAllowedTypes_True.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_PartIsInAllowedNamespacesCaseInsensitive_True.snap
│ ├── TypeObjectSerializerTests.IsTypeAllowed_PartIsInAllowedNamespaces_True.snap
│ └── TypeObjectSerializerTests.IsTypeAllowed_PartIsNotInAllowedNamespaces_False.snap
├── Context.GuidSerializer.Tests
├── Context.GuidSerializers.Tests.csproj
├── GuidSerializerTests.cs
├── Helpers
│ ├── Bar.cs
│ ├── Foo.cs
│ └── FooBarMongoDbContext.cs
└── __snapshots__
│ ├── GuidSerializerTests.Serialize_GuidPropertyGuidSerialized_Successfully.snap
│ └── GuidSerializerTests.Serialize_ObjectPropertyGuidSerialized_Successfully.snap
├── Context.InterferingTests
├── Context.InterferingTests.csproj
├── Helpers
│ ├── Foo.cs
│ └── FooCollectionConfiguration.cs
├── MongoDatabaseBuilderTests.cs
└── __snapshots__
│ └── MongoDatabaseBuilderTests.ConfigureCollection_SetDifferentSettingsToCollection_CollectionConfiguredSuccessfully.snap
├── Context.Tests
├── Context.Tests.csproj
├── Helpers
│ ├── Bar.cs
│ ├── Foo.cs
│ └── Order.cs
├── ImmutableConventionTests.cs
├── ImmutableConventionWithRecordsTests.cs
├── Internal
│ ├── DependencyTypesResolverTests.cs
│ └── __snapshots__
│ │ └── DependencyTypesResolverTests.GetAllowedTypesByDependencies_All_Successful.snap
├── IsExternalInit.cs
├── MongoCollectionBuilderTests.cs
├── MongoCollectionsTests.cs
├── MongoDbContextDataTests.cs
├── MongoDbContextTests.cs
├── MongoTransactionDbContextTests.cs
├── Properties
│ └── AssemblyInfo.cs
└── __snapshots__
│ ├── AbstractImmutableWithAbstractBasePropertyCase.ApplyConvention_SerializeSuccessful.snap
│ ├── AbstractImmutableWithBasePropertyCase.ApplyConvention_SerializeSuccessful.snap
│ ├── AbstractImmutableWithNullableVirtualBasePropertyCase.ApplyConvention_SerializeSuccessful.snap
│ ├── AbstractImmutableWithVirtualBasePropertyCase.ApplyConvention_SerializeSuccessful.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_AddFooBarWithCommit_AllSaved.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_AddFooBarWithRollback_NothingSaved.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_CreateNewTransactionDbContext_OptionsCorrect.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_SetTransactionTransactionOptions_OptionsCorrect.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_TwoTransactionContextWithDifferentObjects_AllSaved.snap
│ ├── MongoTransactionDbContextTests.StartNewTransactionAsync_TwoTransactionContextWithSameObjects_ConcurrencyExceptionAndSaved.snap
│ ├── NullableReferenceTypeCase.ApplyConvention_CtorWithDefault_SerializeSuccessful.snap
│ ├── NullableReferenceTypeCase.ApplyConvention_WithValue_SerializeSuccessful.snap
│ ├── NullableReferenceTypeCase.ApplyConvention_WithoutValueInDbWithoutDefault_SerializeSuccessful.snap
│ ├── NullableReferenceTypeCase.ApplyConvention_WithoutValueInDb_SerializeSuccessful.snap
│ ├── NullableReferenceTypeCase.ApplyConvention_WithoutValue_SerializeSuccessful.snap
│ ├── NullableValueTypeCase.ApplyConvention_WithValue_SerializeSuccessful.snap
│ ├── NullableValueTypeCase.ApplyConvention_WithoutValue_SerializeSuccessful.snap
│ ├── SimpleImmutableCase.ApplyConvention_SerializeSuccessful.snap
│ └── SimpleImmutableWithInterfaceCase.ApplyConvention_SerializeSuccessful.snap
├── Context
├── Context.csproj
├── DefaultDefinitions.cs
├── Exceptions
│ └── MissingAllowedTypesException.cs
├── Extensions
│ └── TypeExtensions.cs
├── IMongoCollectionBuilder.cs
├── IMongoCollectionConfiguration.cs
├── IMongoDatabaseBuilder.cs
├── IMongoDbContext.cs
├── IMongoDbTransaction.cs
├── IMongoTransactionDbContext.cs
├── ImmutableConvention.cs
├── Internal
│ ├── DependencyTypesResolver.cs
│ ├── IMongoCollections.cs
│ ├── MongoCollectionBuilder.cs
│ ├── MongoCollections.cs
│ ├── MongoDatabaseBuilder.cs
│ ├── MongoDbContextData.cs
│ └── TypeObjectSerializer.cs
├── InternalsVisibleTo.cs
├── MongoDbContext.cs
├── MongoInstrumentationExtensions.cs
├── MongoOptions.cs
├── MongoOptionsConfiguration.cs
├── MongoOptionsExtensions.cs
├── MongoServerExtensions.cs
├── MongoTransactionDbContext.cs
└── Properties
│ └── InternalsVisibleTo.cs
├── Dependencies.props
├── Directory.Build.props
├── Directory.Build.targets
├── Migration.Tests
├── Integration
│ ├── Scenario1
│ │ ├── MigrateDownTests.cs
│ │ ├── MigrateUpTests.cs
│ │ ├── TestEntityForDown.cs
│ │ └── TestEntityForUp.cs
│ ├── Scenario2
│ │ ├── MigrateDownTests.cs
│ │ ├── MigrateUpTests.cs
│ │ ├── TestEntityForDown.cs
│ │ └── TestEntityForUp.cs
│ └── SharedMongoDbCollection.cs
├── Migration.Tests.csproj
├── TestMigration1.cs
├── TestMigration2.cs
├── TestMigration3.cs
└── Unit
│ ├── EntityOptionBuilderTests.cs
│ ├── MigrationOptionBuilderTests.cs
│ ├── MigrationRunnerTests.cs
│ ├── TestEntity.cs
│ └── TestMigration.cs
├── Migration
├── Builders
│ ├── EntityOptionBuilder.cs
│ └── MigrationOptionBuilder.cs
├── Contracts
│ ├── IMigration.cs
│ └── IVersioned.cs
├── Exceptions
│ └── InvalidConfigurationException.cs
├── Migration.csproj
├── MigrationExtensions.cs
├── MigrationRunner.cs
├── MigrationSerializer.cs
├── MigrationSerializerProvider.cs
├── Models
│ ├── EntityContext.cs
│ ├── EntityOption.cs
│ ├── MigrationContext.cs
│ └── MigrationOption.cs
└── Readme.md
├── MongoDB.Extensions.sln
├── Package.props
├── Prime.Extensions.Tests
├── AsyncCursorSourceExtensionsTests.cs
├── FilterDefinitionExtensionsTests.cs
├── FindFluentExtensionsTests.cs
├── Helpers
│ ├── Bar.cs
│ └── Foo.cs
├── MongoCollectionExtensionsTests.cs
├── MongoCollectionFindExtensionsTests.cs
├── MongoDatabaseExtensionsTests.cs
├── Prime.Extensions.Tests.csproj
├── UpdateDefinitionExtensionsTests.cs
└── __snapshots__
│ ├── AsyncCursorSourceExtensionsTests.ToDictionaryAsync_FindMultipleDocumentsWithIdAsKey_ReturnRightDocuments.snap
│ ├── AsyncCursorSourceExtensionsTests.ToDictionaryAsync_FindMultipleDocumentsWithNameAsKey_ReturnRightDocuments.snap
│ ├── FilterDefinitionExtensionsTests.ToDefinitionString_DefinitionStringNoIdent_Success.snap
│ ├── FilterDefinitionExtensionsTests.ToDefinitionString_DefinitionStringWithIdent_Success.snap
│ ├── FilterDefinitionExtensionsTests.ToFilterString_FilterStringNoIdent_Success.snap
│ ├── FilterDefinitionExtensionsTests.ToFilterString_FilterStringWithIdent_Success.snap
│ ├── FindFluentExtensionsTests.PrintQuery_PrintOneSingleQuery_OriginalMongoDbQueryPrinted.snap
│ ├── FindFluentExtensionsTests.ToQueryString_ToOneSingleQueryString_OriginalMongoDbQueryPrinted.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindDuplicatedBarIdsAsynchronously_ReturnsDistinctBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindDuplicatedBarIdsSynchronously_ReturnsDistinctBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindFourBarIdsAsynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindFourBarIdsSynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindFourBarNamesAsynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindFourBarNamesSynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionExtensionsTests.FindIds_FindOneId_ReturnsRightBar.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindDuplicatedBarIdsAsynchronously_ReturnsDistinctBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindDuplicatedBarIdsSynchronously_ReturnsDistinctBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindFourBarIdsAsynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindFourBarIdsSynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindFourBarNamesAsynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindFourBarNamesSynchronously_ReturnsRightBars.snap
│ ├── MongoCollectionFindExtensionsTests.FindIds_FindOneId_ReturnsRightBar.snap
│ ├── MongoDatabaseExtensionsTests.GetProfiledOperations_GetAllExecutedOperations_ReturnsAllMongoDBOperations.snap
│ ├── MongoDatabaseExtensionsTests.GetProfiledOperations_GetOneExecutedOperations_ReturnsOneMongoDBOperation.snap
│ ├── UpdateDefinitionExtensionsTests.ToDefinitionString_DefinitionStringNoIdent_Success.snap
│ └── UpdateDefinitionExtensionsTests.ToDefinitionString_DefinitionStringWithIdent_Success.snap
├── Prime.Extensions
├── AsyncCursorSourceExtensions.cs
├── ClientSessionHandleExtensions.cs
├── FilterDefinitionExtensions.cs
├── FindFluentExtensions.cs
├── MongoCollectionExtensions.cs
├── MongoCollectionFindExtensions.cs
├── MongoDatabaseExtensions.cs
├── Prime.Extensions.csproj
├── ProfileLevel.cs
├── ProfilingStatus.cs
├── StringExtensions.cs
└── UpdateDefinitionExtensions.cs
├── ResourceProject.props
├── Session.Tests
├── MongoServerExtensionsTests.cs
├── MongoSessionProviderTests.cs
├── Session.Tests.csproj
└── __snapshots__
│ └── MongoServerExtensionsTests.GiveSession_WhenRefresh_ThenOkResult.snap
├── Session
├── ClientSessionHandleExtensions.cs
├── ISession.cs
├── ISessionProvider.cs
├── ITransactionSession.cs
├── Internal
│ ├── MongoSession.cs
│ ├── MongoSessionProvider.cs
│ └── MongoTransactionSession.cs
├── Models
│ ├── RefreshSession.cs
│ └── SessionId.cs
├── MongoServerSessionExtensions.cs
├── ServiceCollectionExtensions.cs
├── Session.csproj
└── TransactionSessionExtensions.cs
├── TestProject.props
├── Transactions.Tests
├── TransactionCollectionTests.cs
├── Transactions.Tests.csproj
└── User.cs
├── Transactions
├── MongoDbEnlistmentScope.cs
├── MongoTransactionClient.cs
├── MongoTransactionCollection.cs
├── MongoTransactionDatabase.cs
├── MongoTransactionFilteredCollection.cs
├── TransactionClientExtensions.cs
├── TransactionCollectionExtensions.cs
├── TransactionDatabaseExtensions.cs
├── TransactionStore.cs
└── Transactions.csproj
└── Version.props
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-sonarscanner": {
6 | "version": "5.13.1",
7 | "commands": [
8 | "dotnet-sonarscanner"
9 | ]
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Desktop (please complete the following information):**
21 | - OS: [e.g. iOS]
22 | - Version [e.g. 22]
23 |
24 | **Additional context**
25 | Add any other context about the problem here.
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 |
5 | ---
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Summary of the changes (Less than 80 chars)
2 |
3 | - Detail 1
4 | - Detail 2
5 |
6 | Addresses #bugnumber (in this specific format)
7 |
--------------------------------------------------------------------------------
/.github/workflows/pull-request.yml:
--------------------------------------------------------------------------------
1 | name: Pull Request
2 |
3 | on:
4 | pull_request:
5 | branches: ["master"]
6 |
7 | jobs:
8 | tests:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout code
12 | uses: actions/checkout@v4
13 |
14 | - name: Setup .NET
15 | uses: actions/setup-dotnet@v4
16 | with:
17 | dotnet-version: |
18 | 6.x.x
19 | 8.x.x
20 |
21 | - name: Dotnet Test
22 | run: dotnet test src
23 |
24 | # - name: Build, Test and Sonar
25 | # uses: swisslife-oss/actions/pull-request@main
26 | # with:
27 | # sonar_token: ${{ secrets.SONAR_TOKEN }}
28 | # sonar_project_key: "SwissLife-OSS_Mongo-Extensions"
29 | # sonar_project_name: "mongo-extensions"
30 | # pr_number: ${{ github.event.pull_request.number }}
31 | # pr_source_branch: ${{ github.head_ref }}
32 | # pr_target_branch: ${{ github.base_ref }}
33 | # github_repository: ${{ github.repository }}
34 | # sonar_exclusions: ${{ vars.SONAR_EXCLUSIONS }}
35 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - "*"
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@v2
15 | - name: Use .NET SDK from global.json
16 | uses: actions/setup-dotnet@v3
17 | - name: Build, Test and Push
18 | uses: swisslife-oss/actions/release-packages@main
19 | with:
20 | tag: ${{ github.ref_name }}
21 | nuget_api_key: ${{ secrets.NUGET_API_KEY }}
22 | enable_push: 'yes'
23 |
24 | # sonar:
25 | # runs-on: ubuntu-latest
26 | # steps:
27 | # - name: Checkout code
28 | # uses: actions/checkout@v2
29 | # - name: Setup .NET
30 | # uses: actions/setup-dotnet@v3
31 | # with:
32 | # dotnet-version: |
33 | # 8
34 | # - name: Restore tools
35 | # run: dotnet tool restore
36 | # - name: Build, Test and Sonar
37 | # uses: swisslife-oss/actions/release-sonar@main
38 | # with:
39 | # tag: ${{ github.ref_name }}
40 | # sonar_token: ${{ secrets.SONAR_TOKEN }}
41 | # sonar_project_key: 'SwissLife-OSS_Mongo-Extensions'
42 | # sonar_project_name: "mongo-extensions"
43 | # sonar_exclusions: ${{ vars.SONAR_EXCLUSIONS }}
44 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at Philippe.Birbaum@swisslife.ch. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
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 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Swiss Life OSS
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.402",
4 | "rollForward": "latestFeature"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/samples/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
--------------------------------------------------------------------------------
/samples/Context/DataAccess/BlogRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using Models;
6 | using MongoDB.Driver;
7 |
8 | namespace SimpleBlog.DataAccess
9 | {
10 | public class BlogRepository : IBlogRepository
11 | {
12 | private InsertOneOptions _insertOneOptions;
13 | private IMongoCollection _mongoCollection;
14 |
15 | public BlogRepository(ISimpleBlogDbContext simpleBlogDbContext)
16 | {
17 | if (simpleBlogDbContext == null)
18 | throw new ArgumentNullException(nameof(simpleBlogDbContext));
19 |
20 | _mongoCollection = simpleBlogDbContext.CreateCollection();
21 |
22 | _insertOneOptions = new InsertOneOptions()
23 | {
24 | BypassDocumentValidation = false
25 | };
26 | }
27 |
28 | public async Task AddBlogAsync(
29 | Blog blog, CancellationToken cancellationToken)
30 | {
31 | await _mongoCollection
32 | .InsertOneAsync(blog, _insertOneOptions, cancellationToken);
33 | }
34 |
35 | public async Task> GetBlogsAsync(
36 | CancellationToken cancellationToken = default)
37 | {
38 | var findOptions = new FindOptions();
39 |
40 | IAsyncCursor result = await _mongoCollection.FindAsync(
41 | Builders.Filter.Empty, findOptions, cancellationToken);
42 |
43 | return await result.ToListAsync();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/Configuration/BlogCollectionConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Models;
3 | using MongoDB.Driver;
4 | using MongoDB.Extensions.Context;
5 |
6 | namespace SimpleBlog.DataAccess
7 | {
8 | internal class BlogCollectionConfiguration : IMongoCollectionConfiguration
9 | {
10 | public void OnConfiguring(IMongoCollectionBuilder mongoCollectionBuilder)
11 | {
12 | mongoCollectionBuilder
13 | .WithCollectionName("blogs")
14 | .AddBsonClassMap(cm =>
15 | {
16 | cm.AutoMap();
17 | cm.MapIdMember(c => c.Id);
18 | })
19 | .WithCollectionSettings(settings => settings.ReadConcern = ReadConcern.Majority)
20 | .WithCollectionSettings(settings => settings.ReadPreference = ReadPreference.Nearest)
21 | .WithCollectionConfiguration(collection =>
22 | {
23 | var timestampIndex = new CreateIndexModel(
24 | Builders.IndexKeys.Ascending(blog => blog.TimeStamp),
25 | new CreateIndexOptions { Unique = false });
26 |
27 | collection.Indexes.CreateOne(timestampIndex);
28 | });
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/Configuration/TagCollectionConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Models;
2 | using MongoDB.Driver;
3 | using MongoDB.Extensions.Context;
4 | using Tag = Models.Tag;
5 |
6 | namespace SimpleBlog.DataAccess
7 | {
8 | internal class TagCollectionConfiguration : IMongoCollectionConfiguration
9 | {
10 | public void OnConfiguring(IMongoCollectionBuilder mongoCollectionBuilder)
11 | {
12 | mongoCollectionBuilder
13 | .AddBsonClassMap(cm =>
14 | {
15 | cm.AutoMap();
16 | cm.SetIgnoreExtraElements(true);
17 | })
18 | .WithCollectionSettings(setting =>
19 | {
20 | setting.ReadPreference = ReadPreference.Nearest;
21 | setting.ReadConcern = ReadConcern.Available;
22 | setting.WriteConcern = WriteConcern.Acknowledged;
23 | })
24 | .WithCollectionConfiguration(collection =>
25 | {
26 | var timestampIndex = new CreateIndexModel(
27 | Builders.IndexKeys.Ascending(tag => tag.Name),
28 | new CreateIndexOptions { Unique = true });
29 |
30 | collection.Indexes.CreateOne(timestampIndex);
31 | });
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/samples/Context/DataAccess/Configuration/UserCollectionConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Models;
3 | using MongoDB.Bson.Serialization;
4 | using MongoDB.Driver;
5 | using MongoDB.Extensions.Context;
6 |
7 | namespace SimpleBlog.DataAccess
8 | {
9 | internal class UserCollectionConfiguration : IMongoCollectionConfiguration
10 | {
11 | public void OnConfiguring(IMongoCollectionBuilder mongoCollectionBuilder)
12 | {
13 | mongoCollectionBuilder
14 | .WithCollectionName("users")
15 | .AddBsonClassMap(ConfigureUserClassMap())
16 | .WithCollectionSettings(ConfigureCollectionSettings())
17 | .WithCollectionConfiguration(ConfigureIndexes());
18 | }
19 |
20 | private static Action ConfigureCollectionSettings()
21 | {
22 | return setting =>
23 | {
24 | setting.WriteConcern = WriteConcern.WMajority.With(journal: true);
25 | setting.ReadConcern = ReadConcern.Majority;
26 | setting.ReadPreference = ReadPreference.Primary;
27 | };
28 | }
29 |
30 | private static Action> ConfigureIndexes()
31 | {
32 | return collection =>
33 | {
34 | var emailIndex = new CreateIndexModel(
35 | Builders.IndexKeys.Ascending(user => user.Email),
36 | new CreateIndexOptions { Unique = true });
37 |
38 | var nicknameIndex = new CreateIndexModel(
39 | Builders.IndexKeys.Ascending(user => user.Nickname),
40 | new CreateIndexOptions { Unique = true });
41 |
42 | var firstname = new CreateIndexModel(
43 | Builders.IndexKeys.Ascending(user => user.Firstname),
44 | new CreateIndexOptions { Unique = false });
45 |
46 | var secondname = new CreateIndexModel(
47 | Builders.IndexKeys.Ascending(user => user.Lastname),
48 | new CreateIndexOptions { Unique = false });
49 |
50 | collection.Indexes.CreateMany(
51 | new[] { emailIndex, nicknameIndex, firstname, secondname });
52 | };
53 | }
54 |
55 | private static Action> ConfigureUserClassMap()
56 | {
57 | return cm =>
58 | {
59 | cm.AutoMap();
60 | cm.MapIdMember(u => u.UserId);
61 | };
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/samples/Context/DataAccess/DataAccess.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | SimpleBlog.DataAccess
6 | SimpleBlog.DataAccess
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/IBlogRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 |
6 | namespace SimpleBlog.DataAccess
7 | {
8 | public interface IBlogRepository
9 | {
10 | Task AddBlogAsync(
11 | Blog blog, CancellationToken cancellationToken = default);
12 |
13 | Task> GetBlogsAsync(
14 | CancellationToken cancellationToken = default);
15 | }
16 | }
--------------------------------------------------------------------------------
/samples/Context/DataAccess/ITagRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 |
6 | namespace SimpleBlog.DataAccess
7 | {
8 | public interface ITagRepository
9 | {
10 | Task TryAddTagsAsync(
11 | IEnumerable newTags,
12 | CancellationToken cancellationToken = default);
13 |
14 | Task> GetTagsAsync(
15 | CancellationToken cancellationToken = default);
16 | }
17 | }
--------------------------------------------------------------------------------
/samples/Context/DataAccess/IUserRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 |
6 | namespace SimpleBlog.DataAccess
7 | {
8 | public interface IUserRepository
9 | {
10 | Task GetUserAsync(
11 | string userId, CancellationToken cancellationToken = default);
12 |
13 | Task AddUserAsync(
14 | User user, CancellationToken cancellationToken = default);
15 |
16 | Task AttachBlogToUserAsync(
17 | string userId, Guid blogId, CancellationToken cancellationToken = default);
18 | }
19 | }
--------------------------------------------------------------------------------
/samples/Context/DataAccess/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using MongoDB.Extensions.Context;
4 |
5 | namespace SimpleBlog.DataAccess
6 | {
7 | public static class ServiceCollectionExtensions
8 | {
9 | public static IServiceCollection AddBlogDatabase(
10 | this IServiceCollection services, IConfiguration configuration)
11 | {
12 | MongoOptions blogDbOptions = configuration
13 | .GetMongoOptions(WellKnown.Path.SimpleBlogDB);
14 |
15 | services.AddSingleton(blogDbOptions);
16 | services.AddSingleton();
17 | services.AddSingleton();
18 | services.AddSingleton();
19 | services.AddSingleton();
20 |
21 | return services;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/SimpleBlogDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using MongoDB.Bson;
3 | using MongoDB.Bson.Serialization.Serializers;
4 | using MongoDB.Driver;
5 | using MongoDB.Driver.Core.Events;
6 | using MongoDB.Extensions.Context;
7 |
8 | namespace SimpleBlog.DataAccess
9 | {
10 | public class SimpleBlogDbContext : MongoDbContext, ISimpleBlogDbContext
11 | {
12 | public SimpleBlogDbContext(MongoOptions mongoOptions) : base(mongoOptions)
13 | {
14 | }
15 |
16 | protected override void OnConfiguring(IMongoDatabaseBuilder mongoDatabaseBuilder)
17 | {
18 | mongoDatabaseBuilder
19 | .RegisterCamelCaseConventionPack()
20 | .RegisterSerializer(new DateTimeOffsetSerializer())
21 | .ConfigureConnection(con => con.ReadConcern = ReadConcern.Majority)
22 | .ConfigureConnection(con => con.WriteConcern = WriteConcern.WMajority)
23 | .ConfigureConnection(con => con.ReadPreference = ReadPreference.Primary)
24 | .ConfigureCollection(new UserCollectionConfiguration())
25 | .ConfigureCollection(new BlogCollectionConfiguration())
26 | .ConfigureCollection(new TagCollectionConfiguration());
27 | }
28 | }
29 |
30 | public interface ISimpleBlogDbContext : IMongoDbContext
31 | {
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/TagRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using MongoDB.Driver;
7 | using Tag = Models.Tag;
8 |
9 | namespace SimpleBlog.DataAccess
10 | {
11 | public class TagRepository : ITagRepository
12 | {
13 | private IMongoCollection _mongoCollection;
14 |
15 | public TagRepository(ISimpleBlogDbContext simpleBlogDbContext)
16 | {
17 | if (simpleBlogDbContext == null)
18 | throw new ArgumentNullException(nameof(simpleBlogDbContext));
19 |
20 | _mongoCollection = simpleBlogDbContext.CreateCollection();
21 | }
22 |
23 | public async Task> GetTagsAsync(
24 | CancellationToken cancellationToken)
25 | {
26 | var findOptions = new FindOptions();
27 |
28 | IAsyncCursor result = await _mongoCollection.FindAsync(
29 | Builders.Filter.Empty, findOptions, cancellationToken);
30 |
31 | return await result.ToListAsync();
32 | }
33 |
34 | public async Task TryAddTagsAsync(
35 | IEnumerable tags, CancellationToken cancellationToken)
36 | {
37 | var bulkWriteOptions = new BulkWriteOptions();
38 |
39 | IEnumerable> bulkWrites =
40 | tags.Select(tag => new UpdateOneModel(
41 | Builders.Filter.Eq(t => t.Name, tag),
42 | Builders.Update.Inc(t => t.Count, 1))
43 | { IsUpsert = true });
44 |
45 | await _mongoCollection
46 | .BulkWriteAsync(bulkWrites, bulkWriteOptions, cancellationToken);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/UserRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 | using MongoDB.Driver;
6 |
7 | namespace SimpleBlog.DataAccess
8 | {
9 | public class UserRepository : IUserRepository
10 | {
11 | private InsertOneOptions _insertOneOptions;
12 | private IMongoCollection _mongoCollection;
13 |
14 | public UserRepository(ISimpleBlogDbContext simpleBlogDbContext)
15 | {
16 | if (simpleBlogDbContext == null)
17 | throw new ArgumentNullException(nameof(simpleBlogDbContext));
18 |
19 | _mongoCollection = simpleBlogDbContext.CreateCollection();
20 |
21 | _insertOneOptions = new InsertOneOptions()
22 | {
23 | BypassDocumentValidation = false
24 | };
25 | }
26 |
27 | public async Task GetUserAsync(
28 | string userId, CancellationToken cancellationToken= default)
29 | {
30 | FilterDefinition filter = Builders.Filter
31 | .Eq(user => user.UserId, userId);
32 |
33 | return await _mongoCollection
34 | .Find(filter)
35 | .SingleOrDefaultAsync(cancellationToken);
36 | }
37 |
38 | public async Task AddUserAsync(
39 | User user, CancellationToken cancellationToken = default)
40 | {
41 | await _mongoCollection
42 | .InsertOneAsync(user, _insertOneOptions, cancellationToken);
43 | }
44 |
45 | public async Task AttachBlogToUserAsync(
46 | string userId, Guid blogId, CancellationToken cancellationToken = default)
47 | {
48 | UpdateDefinition update = Builders.Update
49 | .AddToSet(u => u.Posts, blogId);
50 |
51 | var updateOptions = new UpdateOptions()
52 | {
53 | IsUpsert = true
54 | };
55 |
56 | await _mongoCollection.UpdateOneAsync(
57 | user => user.UserId == userId, update, updateOptions, cancellationToken);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/samples/Context/DataAccess/WellKnown.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace SimpleBlog.DataAccess
6 | {
7 | public static class WellKnown
8 | {
9 | public static class Path
10 | {
11 | public const string SimpleBlogDB = "SimpleBlog:Database";
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/Context/Domain/BlogService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using Models;
6 | using SimpleBlog.DataAccess;
7 |
8 | namespace SimpleBlog.Domain
9 | {
10 | public class BlogService : IBlogService
11 | {
12 | private readonly IBlogRepository _blogRepository;
13 | private readonly IUserRepository _userRepository;
14 | private readonly ITagRepository _tagRepository;
15 |
16 | public BlogService(
17 | IBlogRepository blogRepository,
18 | IUserRepository userRepository,
19 | ITagRepository tagRepository)
20 | {
21 | _blogRepository = blogRepository;
22 | _userRepository = userRepository;
23 | _tagRepository = tagRepository;
24 | }
25 |
26 | public async Task PostBlogAsync(BlogPost blogPost, CancellationToken cancellationToken)
27 | {
28 | var blog = new Blog()
29 | {
30 | Id = Guid.NewGuid(),
31 | TimeStamp = DateTime.UtcNow,
32 | UserId = blogPost.UserId,
33 | Titel = blogPost.Titel,
34 | Text = blogPost.Text,
35 | Tags = blogPost.Tags
36 | };
37 |
38 | await _blogRepository.AddBlogAsync(blog, cancellationToken);
39 | await _userRepository.AttachBlogToUserAsync(blog.UserId, blog.Id, cancellationToken);
40 | await _tagRepository.TryAddTagsAsync(blogPost.Tags, cancellationToken);
41 | }
42 |
43 | public async Task> GetAllTagsAsync(CancellationToken cancellationToken)
44 | {
45 | return await _tagRepository.GetTagsAsync(cancellationToken);
46 | }
47 |
48 | public async Task> GetAllBlogsAsync(CancellationToken cancellationToken)
49 | {
50 | return await _blogRepository.GetBlogsAsync(cancellationToken);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/samples/Context/Domain/Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | SimpleBlog.Domain
6 | SimpleBlog.Domain
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/samples/Context/Domain/IBlogService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 |
6 | namespace SimpleBlog.Domain
7 | {
8 | public interface IBlogService
9 | {
10 | Task PostBlogAsync(BlogPost blogPost, CancellationToken cancellationToken);
11 | Task> GetAllBlogsAsync(CancellationToken cancellationToken);
12 | Task> GetAllTagsAsync(CancellationToken cancellationToken);
13 | }
14 | }
--------------------------------------------------------------------------------
/samples/Context/Domain/IUserService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using Models;
4 |
5 | namespace SimpleBlog.Domain
6 | {
7 | public interface IUserService
8 | {
9 | Task EnsureUserAsync(string userId, CancellationToken cancellationToken = default);
10 | Task RegisterUserAsync(User newUser, CancellationToken cancellationToken = default);
11 | }
12 | }
--------------------------------------------------------------------------------
/samples/Context/Domain/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace SimpleBlog.Domain
4 | {
5 | public static class ServiceCollectionExtensions
6 | {
7 | public static IServiceCollection AddBlogDomain(
8 | this IServiceCollection services)
9 | {
10 | services.AddSingleton();
11 | services.AddSingleton();
12 |
13 | return services;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/samples/Context/Domain/UserService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Models;
5 | using SimpleBlog.DataAccess;
6 |
7 | namespace SimpleBlog.Domain
8 | {
9 | public class UserService : IUserService
10 | {
11 | private readonly IUserRepository _userRepository;
12 |
13 | public UserService(IUserRepository userRepository)
14 | {
15 | _userRepository = userRepository;
16 | }
17 |
18 | public async Task EnsureUserAsync(
19 | string userId, CancellationToken cancellationToken = default)
20 | {
21 | User user = await _userRepository.GetUserAsync(userId, cancellationToken);
22 |
23 | if(user == null)
24 | {
25 | await RegisterUserAsync(new User()
26 | {
27 | UserId = userId,
28 | Email = $"{userId}@UnknownEmail.ch",
29 | Nickname = $"UnknownNickName-{userId}"
30 | });
31 | }
32 | }
33 |
34 | public async Task RegisterUserAsync(
35 | User newUser, CancellationToken cancellationToken = default)
36 | {
37 | await _userRepository.AddUserAsync(newUser, cancellationToken);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/samples/Context/Host/Controllers/SimpleBlogController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Models;
6 | using SimpleBlog.Domain;
7 |
8 | namespace SimpleBlog.Api.Controllers
9 | {
10 | [ApiController]
11 | [Route("api/[controller]")]
12 | public class SimpleBlogController : ControllerBase
13 | {
14 | private readonly IBlogService _blogService;
15 | private readonly IUserService _userService;
16 |
17 | public SimpleBlogController(
18 | IBlogService blogService, IUserService userService)
19 | {
20 | _blogService = blogService;
21 | _userService = userService;
22 | }
23 |
24 | [HttpPost]
25 | [Route("blogs")]
26 | public async Task PostBlog(
27 | BlogPost blogPost, CancellationToken cancellationToken)
28 | {
29 | await _userService.EnsureUserAsync(blogPost.UserId, cancellationToken);
30 | await _blogService.PostBlogAsync(blogPost, cancellationToken);
31 | }
32 |
33 | [HttpGet]
34 | [Route("blogs")]
35 | public async Task>> GetBlogs(
36 | CancellationToken cancellationToken)
37 | {
38 | IEnumerable result = await _blogService.GetAllBlogsAsync(cancellationToken);
39 |
40 | return Ok(result);
41 | }
42 |
43 | [HttpGet]
44 | [Route("tags")]
45 | public async Task>> GetTags(
46 | CancellationToken cancellationToken)
47 | {
48 | IEnumerable result = await _blogService.GetAllTagsAsync(cancellationToken);
49 |
50 | return Ok(result);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/samples/Context/Host/Host.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | fbbac7be-63d2-4849-8dc4-31492a2367a2
6 | Linux
7 | ..\..
8 | SimpleBlog.Host
9 | SimpleBlog.Host
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/samples/Context/Host/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 | using Squadron;
10 |
11 | namespace SimpleBlog.Api
12 | {
13 | public class Program
14 | {
15 | private static MongoReplicaSetResource _mongoResource;
16 |
17 | public static async Task Main(string[] args)
18 | {
19 | _mongoResource = new MongoReplicaSetResource();
20 |
21 | await _mongoResource.InitializeAsync();
22 |
23 | CreateHostBuilder(args).Build().Run();
24 |
25 | await _mongoResource.DisposeAsync();
26 | }
27 |
28 | public static IHostBuilder CreateHostBuilder(string[] args)
29 | {
30 | string mongoConnectionString = _mongoResource.ConnectionString;
31 | string mongoDatabaseName = _mongoResource
32 | .CreateDatabase()
33 | .DatabaseNamespace
34 | .DatabaseName;
35 |
36 | return Host.CreateDefaultBuilder(args)
37 | .ConfigureLogging(configure =>
38 | {
39 | configure.AddConsole();
40 | })
41 | .ConfigureAppConfiguration(builder =>
42 | {
43 | builder.AddJsonFile("appsettings.json");
44 | builder.AddEnvironmentVariables();
45 | builder.AddInMemoryCollection(new Dictionary()
46 | {
47 | { "SimpleBlog:Database:ConnectionString", mongoConnectionString },
48 | {"SimpleBlog:Database:DatabaseName", mongoDatabaseName }
49 | });
50 | })
51 | .ConfigureWebHostDefaults(webBuilder =>
52 | {
53 | webBuilder.UseStartup();
54 | });
55 | }
56 |
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/samples/Context/Host/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:59489/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "Host": {
12 | "commandName": "Project",
13 | "launchBrowser": true,
14 | "launchUrl": "http://localhost:59490/swagger",
15 | "environmentVariables": {
16 | "ASPNETCORE_ENVIRONMENT": "Development"
17 | },
18 | "applicationUrl": "http://localhost:59490/"
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/samples/Context/Host/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 | using SimpleBlog.DataAccess;
7 | using SimpleBlog.Domain;
8 |
9 | namespace SimpleBlog.Api
10 | {
11 | public class Startup
12 | {
13 | public Startup(IConfiguration configuration)
14 | {
15 | Configuration = configuration;
16 | }
17 |
18 | public IConfiguration Configuration { get; }
19 |
20 | public void ConfigureServices(IServiceCollection services)
21 | {
22 | services.AddControllers();
23 | services.AddBlogDomain();
24 | services.AddBlogDatabase(Configuration);
25 | services.AddSwaggerDocument();
26 |
27 | }
28 |
29 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
30 | {
31 | if (env.IsDevelopment())
32 | {
33 | app.UseDeveloperExceptionPage();
34 | }
35 |
36 | app.UseOpenApi();
37 | app.UseSwaggerUi();
38 |
39 | app.UseHttpsRedirection();
40 |
41 | app.UseRouting();
42 |
43 | app.UseAuthorization();
44 |
45 | app.UseEndpoints(endpoints =>
46 | {
47 | endpoints.MapControllers();
48 | });
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/samples/Context/Host/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/samples/Context/Host/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "SimpleBlog": {
11 | "Database": {
12 | "ConnectionString": "mongodb://localhost:27017",
13 | "DatabaseName": "SimpleBlog"
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/samples/Context/Models/Blog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Models
5 | {
6 | public class BlogPost
7 | {
8 | public string Titel { get; set; }
9 | public string Text { get; set; }
10 | public IEnumerable Tags { get; set; }
11 | public string UserId { get; set; }
12 | }
13 |
14 | public class Blog
15 | {
16 | public Guid Id { get; set; }
17 | public string Titel { get; set; }
18 | public string Text { get; set; }
19 | public DateTime TimeStamp { get; set; }
20 | public IEnumerable Tags { get; set; }
21 | public string UserId { get; set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/samples/Context/Models/Models.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | SimpleBlog.Models
6 | SimpleBlog.Models
7 | false
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/Context/Models/Tag.cs:
--------------------------------------------------------------------------------
1 | namespace Models
2 | {
3 | public class Tag
4 | {
5 | public string Name { get; set; }
6 |
7 | public int Count { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/samples/Context/Models/User.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Models
5 | {
6 | public class User
7 | {
8 | public User()
9 | {
10 | Posts = new List();
11 | }
12 |
13 | public string UserId { get; set; }
14 |
15 | public string Email { get; set; }
16 |
17 | public string Nickname { get; set; }
18 |
19 | public string Firstname { get; set; }
20 |
21 | public string Lastname { get; set; }
22 |
23 | public IEnumerable Posts { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/samples/Migration/Customer.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Extensions.Migration;
2 |
3 | namespace Migration;
4 |
5 | public record Customer(string Id, string Name) : IVersioned
6 | {
7 | public int Version { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/samples/Migration/ExampleMigration.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Bson;
2 | using MongoDB.Extensions.Migration;
3 |
4 | namespace Migration;
5 |
6 | public class ExampleMigration : IMigration
7 | {
8 | public int Version => 1;
9 |
10 | public void Up(BsonDocument document)
11 | {
12 | document["Name"] += " Migrated up to 1";
13 | }
14 |
15 | public void Down(BsonDocument document)
16 | {
17 | document["Name"] += " Migrated down to 0";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/samples/Migration/Migration.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/samples/Migration/Program.cs:
--------------------------------------------------------------------------------
1 | using Migration;
2 | using MongoDB.Extensions.Migration;
3 | using MongoDB.Driver;
4 |
5 | var builder = WebApplication.CreateBuilder(args);
6 |
7 | builder.Services
8 | .AddSingleton(_ => new MongoClient("mongodb://localhost:27017"))
9 | .AddTransient();
10 |
11 | var app = builder.Build();
12 |
13 | app.UseMongoMigration(m => m
14 | .ForEntity(e => e
15 | .AtVersion(1)
16 | .WithMigration(new ExampleMigration())));
17 |
18 | app.MapGet("/customer/{id}", (string id, Repository repo) => repo.GetAsync(id));
19 | app.MapPost("/customer/", (Customer customer, Repository repo) => repo.AddAsync(customer));
20 |
21 | app.Run();
22 |
--------------------------------------------------------------------------------
/samples/Migration/Repository.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Driver;
2 | using MongoDB.Driver.Linq;
3 |
4 | namespace Migration;
5 |
6 | public class Repository
7 | {
8 | private readonly IMongoCollection _collection;
9 |
10 | public Repository(MongoClient client)
11 | {
12 | var database = client.GetDatabase("Example1");
13 | _collection = database.GetCollection("customer");
14 | }
15 |
16 | public Task AddAsync(Customer customer) => _collection.InsertOneAsync(customer);
17 |
18 | public Task GetAsync(string id) => _collection.AsQueryable()
19 | .SingleOrDefaultAsync(c => c.Id == id);
20 | }
21 |
--------------------------------------------------------------------------------
/samples/Migration/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/samples/Migration/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/Context.AllowedTypes.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MongoDB.Extensions.Context.AllowedTypes.Tests
6 | MongoDB.Extensions.Context.AllowedTypes.Tests
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/Helpers/Bar.cs:
--------------------------------------------------------------------------------
1 | namespace MongoDB.Extensions.Context.AllowedTypes.Tests;
2 |
3 | public class Bar
4 | {
5 | public int Id { get; set; }
6 | public string? BarName { get; set; }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/Helpers/Foo.cs:
--------------------------------------------------------------------------------
1 | namespace MongoDB.Extensions.Context.AllowedTypes.Tests;
2 |
3 | public class Foo
4 | {
5 | public int Id { get; set; }
6 | public string? FooName { get; set; }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/Helpers/MongoCollectionFixture.cs:
--------------------------------------------------------------------------------
1 | using Squadron;
2 | using Xunit;
3 |
4 | namespace MongoDB.Extensions.Context.AllowedTypes.Tests;
5 |
6 | public static class CollectionFixtureNames
7 | {
8 | public const string MongoCollectionFixture = "MongoCollectionFixture";
9 | }
10 |
11 | [CollectionDefinition(CollectionFixtureNames.MongoCollectionFixture)]
12 | public class MongoCollectionFixture
13 | : ICollectionFixture
14 | {
15 | }
16 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/Helpers/TestHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace MongoDB.Extensions.Context.AllowedTypes.Tests.Helpers;
5 |
6 | internal static class TestHelpers
7 | {
8 | public static object GetTypeObjectSerializerContent()
9 | {
10 | return new
11 | {
12 | AllowedTypes = TypeObjectSerializer.AllowedTypes
13 | .Select(pair => new KeyValuePair(pair.Key.FullName, pair.Value))
14 | .OrderBy(pair => pair.Key),
15 | AllowedTypesByNamespaces = TypeObjectSerializer.AllowedTypesByNamespaces
16 | .OrderBy(x => x),
17 | AllowedTypesByDependencies = TypeObjectSerializer.AllowedTypesByDependencies
18 | .Except(new[] { "Coverlet" })
19 | .OrderBy(x => x)
20 | };
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Context.AllowedTypes.Tests/MongoDatabaseBuilderTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using MongoDB.Bson.Serialization;
4 | using MongoDB.Driver;
5 | using MongoDB.Extensions.Context.AllowedTypes.Tests.Helpers;
6 | using Snapshooter.Xunit;
7 | using Squadron;
8 | using Xunit;
9 |
10 | namespace MongoDB.Extensions.Context.AllowedTypes.Tests;
11 |
12 | [Collection(CollectionFixtureNames.MongoCollectionFixture)]
13 | public class MongoDatabaseBuilderTests
14 | {
15 | private readonly MongoOptions _mongoOptions;
16 | private readonly IMongoDatabase _mongoDatabase;
17 |
18 | public MongoDatabaseBuilderTests(MongoResource mongoResource)
19 | {
20 | _mongoDatabase = mongoResource.CreateDatabase();
21 | _mongoOptions = new MongoOptions
22 | {
23 | ConnectionString = mongoResource.ConnectionString,
24 | DatabaseName = _mongoDatabase.DatabaseNamespace.DatabaseName
25 | };
26 | }
27 |
28 | [Fact]
29 | public void AddAllowedTypes_AllowedTypesRegisteredByDefault_Success()
30 | {
31 | // Arrange
32 | var mongoDatabaseBuilder = new MongoDatabaseBuilder(_mongoOptions);
33 |
34 | mongoDatabaseBuilder.ClearAllowedTypes();
35 |
36 | // Act
37 | MongoDbContextData context = mongoDatabaseBuilder.Build();
38 |
39 | // Assert
40 | Assert.NotNull(context);
41 | }
42 |
43 | [Fact]
44 | public void AddAllowedTypes_AddAllowedTypesOfAllDependencies_Success()
45 | {
46 | // Arrange
47 | var mongoDatabaseBuilder = new MongoDatabaseBuilder(_mongoOptions);
48 |
49 | mongoDatabaseBuilder.ClearAllowedTypes();
50 |
51 | // Act
52 | mongoDatabaseBuilder.AddAllowedTypesOfAllDependencies();
53 | mongoDatabaseBuilder.Build();
54 |
55 | // Assert
56 | IBsonSerializer