Skip to content

Commit 9952516

Browse files
authored
Merge pull request #25 from EFNext/feat/mongo-integration
MongoDB integration
2 parents 45dc35a + 85a9122 commit 9952516

25 files changed

+1870
-26
lines changed

.devcontainer/devcontainer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
]
1010
},
1111
"ghcr.io/devcontainers/features/node:1": {},
12-
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
12+
"ghcr.io/devcontainers/features/docker-in-docker:2": {
13+
"dockerDashComposeVersion": "none",
14+
"installDockerBuildx": false
15+
}
1316
},
1417
"customizations": {
1518
"vscode": {

.github/workflows/ci.yml

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,25 @@ jobs:
4646
run: dotnet build --no-restore -c Release
4747

4848
- name: Test
49-
run: >-
50-
dotnet test --no-build -c Release
51-
--
52-
--report-trx --report-trx-filename results.trx
53-
--results-directory ./test-results
54-
--coverage
55-
--coverage-output-format cobertura
56-
--coverage-output coverage.xml
49+
# MongoDB integration tests run in the dedicated `mongodb-tests` job —
50+
# list the non-Mongo projects explicitly so Build & Test doesn't need
51+
# Docker or pay the container startup cost on every PR.
52+
run: |
53+
set -e
54+
for proj in \
55+
tests/ExpressiveSharp.Tests \
56+
tests/ExpressiveSharp.IntegrationTests \
57+
tests/ExpressiveSharp.Generator.Tests \
58+
tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests; do
59+
dotnet test --no-build -c Release \
60+
--project "$proj" \
61+
--results-directory ./test-results \
62+
-- \
63+
--report-trx --report-trx-filename "$(basename "$proj").trx" \
64+
--coverage \
65+
--coverage-output-format cobertura \
66+
--coverage-output "$(basename "$proj").coverage.xml"
67+
done
5768
5869
- name: Upload test results
5970
if: always()
@@ -62,15 +73,15 @@ jobs:
6273
name: test-results
6374
path: |
6475
./test-results/*.trx
65-
./test-results/**/coverage.xml
76+
./test-results/*.coverage.xml
6677
retention-days: 14
6778

6879
- name: Upload coverage to Codecov
6980
if: always()
7081
uses: codecov/codecov-action@v5
7182
with:
7283
token: ${{ secrets.CODECOV_TOKEN }}
73-
files: ./test-results/**/coverage.xml
84+
files: ./test-results/*.coverage.xml
7485
fail_ci_if_error: false
7586

7687
- name: Test report
@@ -187,3 +198,67 @@ jobs:
187198
name: Container Test Results (${{ matrix.database }})
188199
path: ./test-results/*.trx
189200
reporter: dotnet-trx
201+
202+
mongodb-tests:
203+
name: Container Tests (MongoDB)
204+
runs-on: ubuntu-latest
205+
needs: build-and-test
206+
timeout-minutes: 10
207+
208+
env:
209+
CI: true
210+
211+
steps:
212+
- name: Checkout
213+
uses: actions/checkout@v4
214+
215+
- name: Setup .NET SDKs
216+
uses: actions/setup-dotnet@v4
217+
with:
218+
dotnet-version: |
219+
8.0.x
220+
9.0.x
221+
10.0.x
222+
223+
- name: Cache NuGet packages
224+
uses: actions/cache@v4
225+
with:
226+
path: ~/.nuget/packages
227+
key: nuget-${{ runner.os }}-MongoDB-${{ hashFiles('**/*.csproj', 'Directory.Packages.props') }}
228+
restore-keys: |
229+
nuget-${{ runner.os }}-MongoDB-
230+
nuget-${{ runner.os }}-
231+
232+
- name: Restore
233+
run: >-
234+
dotnet restore
235+
tests/ExpressiveSharp.MongoDB.IntegrationTests/ExpressiveSharp.MongoDB.IntegrationTests.csproj
236+
237+
- name: Build
238+
run: >-
239+
dotnet build --no-restore -c Release
240+
tests/ExpressiveSharp.MongoDB.IntegrationTests/ExpressiveSharp.MongoDB.IntegrationTests.csproj
241+
242+
- name: Test
243+
run: >-
244+
dotnet test --no-build -c Release
245+
--project tests/ExpressiveSharp.MongoDB.IntegrationTests
246+
--results-directory ./test-results
247+
--
248+
--report-trx --report-trx-filename results.trx
249+
250+
- name: Upload test results
251+
if: always()
252+
uses: actions/upload-artifact@v4
253+
with:
254+
name: container-test-results-MongoDB
255+
path: ./test-results/*.trx
256+
retention-days: 14
257+
258+
- name: Test report
259+
if: always()
260+
uses: dorny/test-reporter@v1
261+
with:
262+
name: Container Test Results (MongoDB)
263+
path: ./test-results/*.trx
264+
reporter: dotnet-trx

Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@
2525
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.3.0" />
2626
<PackageVersion Include="Testcontainers.MySql" Version="4.3.0" />
2727
<PackageVersion Include="Microsoft.EntityFrameworkCore.Cosmos" Version="8.0.25" />
28+
<PackageVersion Include="MongoDB.Driver" Version="3.0.0" />
29+
<PackageVersion Include="Testcontainers.MongoDb" Version="4.3.0" />
2830
</ItemGroup>
2931
</Project>

ExpressiveSharp.slnx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
<Project Path="src/ExpressiveSharp.Generator/ExpressiveSharp.Generator.csproj" />
1616
<Project Path="src/ExpressiveSharp.Abstractions/ExpressiveSharp.Abstractions.csproj" />
1717
<Project Path="src/ExpressiveSharp/ExpressiveSharp.csproj" />
18+
<Project Path="src/ExpressiveSharp.MongoDB/ExpressiveSharp.MongoDB.csproj" />
1819
</Folder>
1920
<Folder Name="/tests/">
2021
<Project Path="tests/ExpressiveSharp.Generator.Tests/ExpressiveSharp.Generator.Tests.csproj" />
2122
<Project Path="tests/ExpressiveSharp.IntegrationTests/ExpressiveSharp.IntegrationTests.csproj" />
2223
<Project Path="tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests.csproj" />
2324
<Project Path="tests/ExpressiveSharp.Tests/ExpressiveSharp.Tests.csproj" />
25+
<Project Path="tests/ExpressiveSharp.MongoDB.IntegrationTests/ExpressiveSharp.MongoDB.IntegrationTests.csproj" />
2426
<File Path="tests/Directory.Build.props" />
2527
</Folder>
2628
</Solution>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using ExpressiveSharp.MongoDB.Extensions;
2+
using ExpressiveSharp.Services;
3+
using MongoDB.Driver;
4+
5+
namespace ExpressiveSharp.MongoDB;
6+
7+
/// <summary>
8+
/// A wrapper around <see cref="IMongoCollection{TDocument}"/> that provides an
9+
/// <see cref="IExpressiveMongoQueryable{T}"/> for delegate-based LINQ queries
10+
/// with automatic <c>[Expressive]</c> member expansion.
11+
/// </summary>
12+
/// <remarks>
13+
/// Analogous to <c>ExpressiveDbSet&lt;TEntity&gt;</c> in the EF Core integration.
14+
/// CRUD operations delegate directly to the inner collection.
15+
/// </remarks>
16+
/// <example>
17+
/// <code>
18+
/// var orders = new ExpressiveMongoCollection&lt;Order&gt;(collection);
19+
/// var results = await orders.AsQueryable()
20+
/// .Where(o => o.Customer?.Name == "Alice")
21+
/// .ToListAsync();
22+
/// </code>
23+
/// </example>
24+
public class ExpressiveMongoCollection<TDocument>
25+
{
26+
private readonly IMongoCollection<TDocument> _inner;
27+
private readonly ExpressiveOptions _options;
28+
29+
/// <summary>
30+
/// Creates a new <see cref="ExpressiveMongoCollection{TDocument}"/> wrapping the specified collection.
31+
/// </summary>
32+
/// <param name="inner">The underlying MongoDB collection.</param>
33+
/// <param name="options">
34+
/// Optional <see cref="ExpressiveOptions"/> controlling the transformer pipeline.
35+
/// When <c>null</c>, <see cref="MongoExpressiveOptions.CreateDefault"/> is used.
36+
/// </param>
37+
public ExpressiveMongoCollection(IMongoCollection<TDocument> inner, ExpressiveOptions? options = null)
38+
{
39+
_inner = inner ?? throw new ArgumentNullException(nameof(inner));
40+
_options = options ?? MongoExpressiveOptions.CreateDefault();
41+
}
42+
43+
/// <summary>
44+
/// Gets the underlying <see cref="IMongoCollection{TDocument}"/> for direct access
45+
/// to non-LINQ operations (inserts, updates, deletes, aggregation pipeline, etc.).
46+
/// </summary>
47+
public IMongoCollection<TDocument> Inner => _inner;
48+
49+
/// <summary>
50+
/// Returns an <see cref="IExpressiveMongoQueryable{T}"/> that supports delegate-based
51+
/// LINQ with modern C# syntax and automatic <c>[Expressive]</c> expansion.
52+
/// </summary>
53+
/// <param name="aggregateOptions">Optional MongoDB aggregation options.</param>
54+
public IExpressiveMongoQueryable<TDocument> AsQueryable(AggregateOptions? aggregateOptions = null)
55+
=> _inner.AsExpressive(_options, aggregateOptions);
56+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<Description>MongoDB Driver integration for ExpressiveSharp — automatically expands [Expressive] members in MongoDB LINQ queries</Description>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<InternalsVisibleTo Include="ExpressiveSharp.MongoDB.IntegrationTests" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="MongoDB.Driver" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\ExpressiveSharp\ExpressiveSharp.csproj" />
17+
</ItemGroup>
18+
19+
</Project>

0 commit comments

Comments
 (0)