Skip to content

Commit 73c6b89

Browse files
ajcvickersCopilot
andauthored
EF-273: Pure refactoring (no behavior change) moving code out of MongoClientWrapper (#252)
* EF-273: Pure refactoring (no behavior change) moving code out of MongoClientWrapper * Update src/MongoDB.EntityFrameworkCore/Storage/MongoDatabaseCreator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/MongoDB.EntityFrameworkCore/Storage/MongoDatabaseCreator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Review updates. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent fe3ce33 commit 73c6b89

File tree

8 files changed

+1397
-1508
lines changed

8 files changed

+1397
-1508
lines changed

src/MongoDB.EntityFrameworkCore/Extensions/MongoDatabaseFacadeExtensions.cs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public static void CreateIndex(this DatabaseFacade databaseFacade, IIndex index)
4242
{
4343
ArgumentNullException.ThrowIfNull(index);
4444

45-
((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context.GetService<IMongoClientWrapper>().CreateIndex(index);
45+
GetDatabaseCreator(databaseFacade).CreateIndex(index);
4646
}
4747

4848
/// <summary>
@@ -57,8 +57,7 @@ public static Task CreateIndexAsync(this DatabaseFacade databaseFacade, IIndex i
5757
{
5858
ArgumentNullException.ThrowIfNull(index);
5959

60-
return ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context.GetService<IMongoClientWrapper>()
61-
.CreateIndexAsync(index, cancellationToken);
60+
return GetDatabaseCreator(databaseFacade).CreateIndexAsync(index, cancellationToken);
6261
}
6362

6463
/// <summary>
@@ -67,21 +66,15 @@ public static Task CreateIndexAsync(this DatabaseFacade databaseFacade, IIndex i
6766
/// </summary>
6867
/// <param name="databaseFacade">The <see cref="DatabaseFacade"/> from the EF Core <see cref="Microsoft.EntityFrameworkCore.DbContext"/>.</param>
6968
public static void CreateMissingIndexes(this DatabaseFacade databaseFacade)
70-
{
71-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
72-
context.GetService<IMongoClientWrapper>().CreateMissingIndexes(context.GetService<IDesignTimeModel>().Model);
73-
}
69+
=> GetDatabaseCreator(databaseFacade).CreateMissingIndexes();
7470

7571
/// <summary>
7672
/// Creates missing Atlas vector indexes in the MongoDB database for all <see cref="IIndex"/> definitions in the EF Core model for
7773
/// which there is not already an index in the database.
7874
/// </summary>
7975
/// <param name="databaseFacade">The <see cref="DatabaseFacade"/> from the EF Core <see cref="Microsoft.EntityFrameworkCore.DbContext"/>.</param>
8076
public static void CreateMissingVectorIndexes(this DatabaseFacade databaseFacade)
81-
{
82-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
83-
context.GetService<IMongoClientWrapper>().CreateMissingVectorIndexes(context.GetService<IDesignTimeModel>().Model);
84-
}
77+
=> GetDatabaseCreator(databaseFacade).CreateMissingVectorIndexes();
8578

8679
/// <summary>
8780
/// Creates indexes in the MongoDB database for all <see cref="IIndex"/> definitions in the EF Core model for which there
@@ -91,10 +84,7 @@ public static void CreateMissingVectorIndexes(this DatabaseFacade databaseFacade
9184
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
9285
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
9386
public static Task CreateMissingIndexesAsync(this DatabaseFacade databaseFacade, CancellationToken cancellationToken = default)
94-
{
95-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
96-
return context.GetService<IMongoClientWrapper>().CreateMissingIndexesAsync(context.GetService<IDesignTimeModel>().Model, cancellationToken);
97-
}
87+
=> GetDatabaseCreator(databaseFacade).CreateMissingIndexesAsync(cancellationToken);
9888

9989
/// <summary>
10090
/// Creates missing Atlas vector indexes in the MongoDB database for all <see cref="IIndex"/> definitions in the EF Core model for
@@ -104,10 +94,7 @@ public static Task CreateMissingIndexesAsync(this DatabaseFacade databaseFacade,
10494
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
10595
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
10696
public static Task CreateMissingVectorIndexesAsync(this DatabaseFacade databaseFacade, CancellationToken cancellationToken = default)
107-
{
108-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
109-
return context.GetService<IMongoClientWrapper>().CreateMissingVectorIndexesAsync(context.GetService<IDesignTimeModel>().Model, cancellationToken);
110-
}
97+
=> GetDatabaseCreator(databaseFacade).CreateMissingVectorIndexesAsync(cancellationToken);
11198

11299
/// <summary>
113100
/// Blocks until all vector indexes in the mapped collections are reporting the 'READY' state.
@@ -117,10 +104,7 @@ public static Task CreateMissingVectorIndexesAsync(this DatabaseFacade databaseF
117104
/// The default is 15 seconds. Zero seconds means no timeout.</param>
118105
/// <exception cref="InvalidOperationException">if the timeout expires before all indexes are 'READY'.</exception>
119106
public static void WaitForVectorIndexes(this DatabaseFacade databaseFacade, TimeSpan? timeout = null)
120-
{
121-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
122-
context.GetService<IMongoClientWrapper>().WaitForVectorIndexes(context.GetService<IDesignTimeModel>().Model, timeout);
123-
}
107+
=> GetDatabaseCreator(databaseFacade).WaitForVectorIndexes(timeout);
124108

125109
/// <summary>
126110
/// Blocks until all vector indexes in the mapped collections are reporting the 'READY' state.
@@ -132,10 +116,7 @@ public static void WaitForVectorIndexes(this DatabaseFacade databaseFacade, Time
132116
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
133117
/// <exception cref="InvalidOperationException">if the timeout expires before all indexes are 'READY'.</exception>
134118
public static Task WaitForVectorIndexesAsync(this DatabaseFacade databaseFacade, TimeSpan? timeout = null, CancellationToken cancellationToken = default)
135-
{
136-
var context = ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context;
137-
return context.GetService<IMongoClientWrapper>().WaitForVectorIndexesAsync(context.GetService<IDesignTimeModel>().Model, timeout, cancellationToken);
138-
}
119+
=> GetDatabaseCreator(databaseFacade).WaitForVectorIndexesAsync(timeout, cancellationToken);
139120

140121
/// <summary>
141122
/// Ensures that the database for the context exists. If it exists, no action is taken. If it does not
@@ -146,7 +127,7 @@ public static Task WaitForVectorIndexesAsync(this DatabaseFacade databaseFacade,
146127
/// <param name="options">An <see cref="MongoDatabaseCreationOptions"/> object specifying additional actions to be taken.</param>
147128
/// <returns><see langword="true" /> if the database is created, <see langword="false" /> if it already existed.</returns>
148129
public static bool EnsureCreated(this DatabaseFacade databaseFacade, MongoDatabaseCreationOptions options)
149-
=> ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context.GetService<IMongoDatabaseCreator>().EnsureCreated(options);
130+
=> GetDatabaseCreator(databaseFacade).EnsureCreated(options);
150131

151132
/// <summary>
152133
/// Asynchronously ensures that the database for the context exists. If it exists, no action is taken. If it does not
@@ -188,4 +169,7 @@ public static Task<IDbContextTransaction> BeginTransactionAsync(
188169

189170
private static IMongoTransactionManager GetMongoTransactionManager(DatabaseFacade databaseFacade)
190171
=> (IMongoTransactionManager)((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.TransactionManager;
172+
173+
private static IMongoDatabaseCreator GetDatabaseCreator(DatabaseFacade databaseFacade)
174+
=> ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context.GetService<IMongoDatabaseCreator>();
191175
}

src/MongoDB.EntityFrameworkCore/Metadata/MongoDatabaseCreationOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ namespace MongoDB.EntityFrameworkCore.Metadata;
1919

2020
/// <summary>
2121
/// Creates a <see cref="MongoDatabaseCreationOptions"/> to determine which additional actions are taken when
22-
/// <see cref="MongoDB.EntityFrameworkCore.Extensions.MongoDatabaseFacadeExtensions.EnsureCreated"/> or
23-
/// <see cref="MongoDB.EntityFrameworkCore.Extensions.MongoDatabaseFacadeExtensions.EnsureCreatedAsync"/>
22+
/// <see cref="MongoDB.EntityFrameworkCore.MongoDatabaseFacadeExtensions.EnsureCreated"/> or
23+
/// <see cref="MongoDB.EntityFrameworkCore.MongoDatabaseFacadeExtensions.EnsureCreatedAsync"/>
2424
/// </summary>
2525
/// <param name="CreateMissingCollections">Creates any MongoDB database collections that do not already exist. The default is true.</param>
2626
/// <param name="CreateMissingIndexes">Creates any non-Atlas MongoDB indexes that do not already exist. The default is true.</param>

src/MongoDB.EntityFrameworkCore/Storage/IMongoClientWrapper.cs

Lines changed: 15 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
using System.Collections.Generic;
1818
using System.Threading;
1919
using System.Threading.Tasks;
20-
using Microsoft.EntityFrameworkCore.Metadata;
2120
using MongoDB.Driver;
22-
using MongoDB.EntityFrameworkCore.Metadata;
2321
using MongoDB.EntityFrameworkCore.Query;
2422

2523
namespace MongoDB.EntityFrameworkCore.Storage;
@@ -31,6 +29,21 @@ namespace MongoDB.EntityFrameworkCore.Storage;
3129
/// </summary>
3230
public interface IMongoClientWrapper
3331
{
32+
/// <summary>
33+
/// The underlying <see cref="IMongoClient"/>. Accessing this may cause the underlying client to be created.
34+
/// </summary>
35+
IMongoClient Client { get; }
36+
37+
/// <summary>
38+
/// The underlying <see cref="IMongoDatabase"/>. Accessing this may cause the underlying client to be created.
39+
/// </summary>
40+
IMongoDatabase Database { get; }
41+
42+
/// <summary>
43+
/// Gets the name of the underlying <see cref="IMongoDatabase"/>. Accessing this may cause the underlying client to be created.
44+
/// </summary>
45+
string DatabaseName { get; }
46+
3447
/// <summary>
3548
/// Get an <see cref="IMongoCollection{T}"/> for the given <paramref name="collectionName"/>.
3649
/// </summary>
@@ -49,146 +62,6 @@ public interface IMongoClientWrapper
4962
/// <returns>An <see cref="IEnumerable{T}"/> containing the items returned by the query.</returns>
5063
IEnumerable<T> Execute<T>(MongoExecutableQuery executableQuery, out Action log);
5164

52-
/// <summary>
53-
/// Create a new database with the name specified in the connection options.
54-
/// </summary>
55-
/// <remarks>If the database already exists only new collections will be created.</remarks>
56-
/// <param name="model">The <see cref="IDesignTimeModel"/> that informs how the database should be created.</param>
57-
/// <returns><see langword="true" /> if the database was created from scratch, <see langword="false" /> if it already existed.</returns>
58-
bool CreateDatabase(IDesignTimeModel model);
59-
60-
/// <summary>
61-
/// Create a new database with the name specified in the connection options.
62-
/// </summary>
63-
/// <remarks>If the database already exists only new collections will be created.</remarks>
64-
/// <param name="model">The <see cref="IDesignTimeModel"/> that informs how the database should be created.</param>
65-
/// <param name="options">An <see cref="MongoDatabaseCreationOptions"/> object specifying additional actions to be taken.</param>
66-
/// <param name="seed">A delegate called to seed the database before any Atlas indexes are created.</param>
67-
/// <returns><see langword="true" /> if the database was created from scratch, <see langword="false" /> if it already existed.</returns>
68-
bool CreateDatabase(IDesignTimeModel model, MongoDatabaseCreationOptions options, Action? seed);
69-
70-
/// <summary>
71-
/// Create a new database with the name specified in the connection options asynchronously.
72-
/// </summary>
73-
/// <remarks>If the database already exists only new collections will be created.</remarks>
74-
/// <param name="model">The <see cref="IDesignTimeModel"/> that informs how the database should be created.</param>
75-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
76-
/// <returns>
77-
/// A <see cref="Task"/> that, when resolved, will be
78-
/// <see langword="true" /> if the database was created from scratch, <see langword="false" /> if it already existed.
79-
/// </returns>
80-
Task<bool> CreateDatabaseAsync(IDesignTimeModel model, CancellationToken cancellationToken = default);
81-
82-
/// <summary>
83-
/// Create a new database with the name specified in the connection options asynchronously.
84-
/// </summary>
85-
/// <remarks>If the database already exists only new collections will be created.</remarks>
86-
/// <param name="model">The <see cref="IDesignTimeModel"/> that informs how the database should be created.</param>
87-
/// <param name="options">An <see cref="MongoDatabaseCreationOptions"/> object specifying additional actions to be taken.</param>
88-
/// <param name="seedAsync">A delegate called to seed the database before any Atlas indexes are created.</param>
89-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
90-
/// <returns>
91-
/// A <see cref="Task"/> that, when resolved, will be
92-
/// <see langword="true" /> if the database was created from scratch, <see langword="false" /> if it already existed.
93-
/// </returns>
94-
Task<bool> CreateDatabaseAsync(IDesignTimeModel model, MongoDatabaseCreationOptions options, Func<CancellationToken, Task>? seedAsync, CancellationToken cancellationToken = default);
95-
96-
/// <summary>
97-
/// Delete the database specified in the connection options.
98-
/// </summary>
99-
/// <returns><see langword="true" /> if the database was deleted, <see langword="false" /> if it did not exist.</returns>
100-
bool DeleteDatabase();
101-
102-
/// <summary>
103-
/// Delete the database specified in the connection options asynchronously.
104-
/// </summary>
105-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
106-
/// <returns>
107-
/// A <see cref="Task"/> that, when resolved, will be
108-
/// <see langword="true" /> if the database was deleted, <see langword="false" /> if it already existed.
109-
/// </returns>
110-
Task<bool> DeleteDatabaseAsync(CancellationToken cancellationToken = default);
111-
112-
/// <summary>
113-
/// Determine if the database already exists or not.
114-
/// </summary>
115-
/// <returns><see langword="true" /> if the database exists, <see langword="false" /> if it does not.</returns>
116-
bool DatabaseExists();
117-
118-
/// <summary>
119-
/// Determine if the database already exists or not asynchronously.
120-
/// </summary>
121-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
122-
/// <returns>
123-
/// A <see cref="Task"/> that, when resolved, will be
124-
/// <see langword="true" /> if the database exists, <see langword="false" /> if it does not.
125-
/// </returns>
126-
Task<bool> DatabaseExistsAsync(CancellationToken cancellationToken = default);
127-
128-
/// <summary>
129-
/// Creates an index in MongoDB based on the EF Core <see cref="IIndex"/> definition. No attempt is made to check that the index
130-
/// does not already exist and can therefore be created. The index may be an Atlas index or a normal MongoDB index.
131-
/// </summary>
132-
/// <param name="index">The <see cref="IIndex"/> definition.</param>
133-
void CreateIndex(IIndex index);
134-
135-
/// <summary>
136-
/// Creates an index in MongoDB based on the EF Core <see cref="IIndex"/> definition. No attempt is made to check that the index
137-
/// does not already exist and can therefore be created. The index may be an Atlas index or a normal MongoDB index.
138-
/// </summary>
139-
/// <param name="index">The <see cref="IIndex"/> definition.</param>
140-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
141-
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
142-
Task CreateIndexAsync(IIndex index, CancellationToken cancellationToken = default);
143-
144-
/// <summary>
145-
/// Creates any non-Atlas MongoDB indexes defined in the EF Core model that do not already exist.
146-
/// </summary>
147-
/// <param name="model">The EF Core <see cref="IModel"/>.</param>
148-
void CreateMissingIndexes(IModel model);
149-
150-
/// <summary>
151-
/// Creates any non-Atlas MongoDB indexes defined in the EF Core model that do not already exist.
152-
/// </summary>
153-
/// <param name="model">The EF Core <see cref="IModel"/>.</param>
154-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
155-
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
156-
Task CreateMissingIndexesAsync(IModel model, CancellationToken cancellationToken = default);
157-
158-
/// <summary>
159-
/// Creates any MongoDB Atlas vector indexes defined in the EF Core model that do not already exist.
160-
/// </summary>
161-
/// <param name="model">The EF Core <see cref="IModel"/>.</param>
162-
void CreateMissingVectorIndexes(IModel model);
163-
164-
/// <summary>
165-
/// Creates any MongoDB Atlas vector indexes defined in the EF Core model that do not already exist.
166-
/// </summary>
167-
/// <param name="model">The EF Core <see cref="IModel"/>.</param>
168-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
169-
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
170-
Task CreateMissingVectorIndexesAsync(IModel model, CancellationToken cancellationToken = default);
171-
172-
/// <summary>
173-
/// Blocks until all vector indexes in the mapped collections are reporting the 'READY' state.
174-
/// </summary>
175-
/// <param name="model">The EF Core <see cref="IModel"/></param>
176-
/// <param name="timeout">The minimum amount of time to wait for all indexes to be 'READY' before aborting.
177-
/// The default is 15 seconds. Zero seconds means no timeout.</param>
178-
/// <exception cref="InvalidOperationException">if the timeout expires before all indexes are 'READY'.</exception>
179-
void WaitForVectorIndexes(IModel model, TimeSpan? timeout = null);
180-
181-
/// <summary>
182-
/// Blocks until all vector indexes in the mapped collections are reporting the 'READY' state.
183-
/// </summary>
184-
/// <param name="model">The EF Core <see cref="IModel"/></param>
185-
/// <param name="timeout">The minimum amount of time to wait for all indexes to be 'READY' before aborting.
186-
/// The default is 15 seconds. Zero seconds means no timeout.</param>
187-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel this asynchronous request.</param>
188-
/// <returns>A <see cref="Task"/> to track this async operation.</returns>
189-
/// <exception cref="InvalidOperationException">if the timeout expires before all indexes are 'READY'.</exception>
190-
Task WaitForVectorIndexesAsync(IModel model, TimeSpan? timeout = null, CancellationToken cancellationToken = default);
191-
19265
/// <summary>
19366
/// Start a new client session.
19467
/// </summary>

0 commit comments

Comments
 (0)