Skip to content

Commit f86cf6e

Browse files
committed
Update existing and add new UseJet signatures.
1 parent 3f19b26 commit f86cf6e

File tree

3 files changed

+167
-65
lines changed

3 files changed

+167
-65
lines changed

src/EFCore.Jet/Extensions/JetDbContextOptionsBuilderExtensions.cs

Lines changed: 149 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,71 @@ namespace Microsoft.EntityFrameworkCore
1818
/// </summary>
1919
public static class JetDbContextOptionsBuilderExtensions
2020
{
21+
#region Connection String
22+
23+
/// <summary>
24+
/// Configures the context to connect to a Microsoft Jet database.
25+
/// </summary>
26+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
27+
/// <param name="connectionString"> The connection string of the database to connect to. The underlying data
28+
/// access provider (ODBC or OLE DB) will be inferred from the style of this connection string. </param>
29+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
30+
/// <returns> The options builder so that further configuration can be chained. </returns>
31+
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
32+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
33+
[NotNull] string connectionString,
34+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
35+
where TContext : DbContext
36+
=> (DbContextOptionsBuilder<TContext>) UseJet((DbContextOptionsBuilder) optionsBuilder, connectionString, jetOptionsAction);
37+
38+
/// <summary>
39+
/// Configures the context to connect to a Microsoft Jet database.
40+
/// </summary>
41+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
42+
/// <param name="connectionString"> The connection string of the database to connect to. The underlying data
43+
/// access provider (ODBC or OLE DB) will be inferred from the style of this connection string. </param>
44+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
45+
/// <returns> The options builder so that further configuration can be chained. </returns>
46+
public static DbContextOptionsBuilder UseJet(
47+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
48+
[NotNull] string connectionString,
49+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
50+
{
51+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
52+
Check.NotEmpty(connectionString, nameof(connectionString));
53+
54+
return UseJetCore(optionsBuilder, connectionString, null, JetConnection.GetDataAccessProviderType(connectionString), jetOptionsAction);
55+
}
56+
2157
/// <summary>
2258
/// Configures the context to connect to a Microsoft Jet database.
2359
/// </summary>
2460
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
2561
/// <param name="connectionString"> The connection string of the database to connect to. </param>
26-
/// <param name="dataAccessProviderFactory">A `OdbcFactory` or `OleDbFactory` object to be used for all
62+
/// <param name="dataAccessProviderFactory">An `OdbcFactory` or `OleDbFactory` object to be used for all
63+
/// data access operations by the Jet connection.</param>
64+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
65+
/// <returns> The options builder so that further configuration can be chained. </returns>
66+
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
67+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
68+
[NotNull] string connectionString,
69+
[NotNull] DbProviderFactory dataAccessProviderFactory,
70+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
71+
where TContext : DbContext
72+
{
73+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
74+
Check.NotEmpty(connectionString, nameof(connectionString));
75+
Check.NotNull(dataAccessProviderFactory, nameof(dataAccessProviderFactory));
76+
77+
return (DbContextOptionsBuilder<TContext>) UseJet((DbContextOptionsBuilder) optionsBuilder, connectionString, dataAccessProviderFactory, jetOptionsAction);
78+
}
79+
80+
/// <summary>
81+
/// Configures the context to connect to a Microsoft Jet database.
82+
/// </summary>
83+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
84+
/// <param name="connectionString"> The connection string of the database to connect to. </param>
85+
/// <param name="dataAccessProviderFactory">An `OdbcFactory` or `OleDbFactory` object to be used for all
2786
/// data access operations by the Jet connection.</param>
2887
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
2988
/// <returns> The options builder so that further configuration can be chained. </returns>
@@ -37,22 +96,78 @@ public static DbContextOptionsBuilder UseJet(
3796
Check.NotEmpty(connectionString, nameof(connectionString));
3897
Check.NotNull(dataAccessProviderFactory, nameof(dataAccessProviderFactory));
3998

40-
return UseJetCore(optionsBuilder, connectionString, dataAccessProviderFactory, jetOptionsAction);
99+
return UseJetCore(optionsBuilder, connectionString, dataAccessProviderFactory, null, jetOptionsAction);
100+
}
101+
102+
/// <summary>
103+
/// Configures the context to connect to a Microsoft Jet database.
104+
/// </summary>
105+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
106+
/// <param name="connectionString"> The connection string of the database to connect to. </param>
107+
/// <param name="dataAccessProviderType">The type of the data access provider (`Odbc` or `OleDb`) to be used for all
108+
/// data access operations by the Jet connection.</param>
109+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
110+
/// <returns> The options builder so that further configuration can be chained. </returns>
111+
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
112+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
113+
[NotNull] string connectionString,
114+
DataAccessProviderType dataAccessProviderType,
115+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
116+
where TContext : DbContext
117+
{
118+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
119+
Check.NotEmpty(connectionString, nameof(connectionString));
120+
121+
return (DbContextOptionsBuilder<TContext>) UseJet((DbContextOptionsBuilder)optionsBuilder, connectionString, dataAccessProviderType, jetOptionsAction);
122+
}
123+
124+
/// <summary>
125+
/// Configures the context to connect to a Microsoft Jet database.
126+
/// </summary>
127+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
128+
/// <param name="connectionString"> The connection string of the database to connect to. </param>
129+
/// <param name="dataAccessProviderType">The type of the data access provider (`Odbc` or `OleDb`) to be used for all
130+
/// data access operations by the Jet connection.</param>
131+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
132+
/// <returns> The options builder so that further configuration can be chained. </returns>
133+
public static DbContextOptionsBuilder UseJet(
134+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
135+
[NotNull] string connectionString,
136+
DataAccessProviderType dataAccessProviderType,
137+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
138+
{
139+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
140+
Check.NotEmpty(connectionString, nameof(connectionString));
141+
142+
return UseJetCore(optionsBuilder, connectionString, null, dataAccessProviderType, jetOptionsAction);
41143
}
42144

145+
internal static DbContextOptionsBuilder UseJetWithoutPredefinedDataAccessProvider(
146+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
147+
[NotNull] string connectionString,
148+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
149+
=> UseJetCore(optionsBuilder, connectionString, null, null, jetOptionsAction);
150+
43151
private static DbContextOptionsBuilder UseJetCore(
44152
[NotNull] DbContextOptionsBuilder optionsBuilder,
45153
[NotNull] string connectionString,
46154
[CanBeNull] DbProviderFactory dataAccessProviderFactory,
155+
[CanBeNull] DataAccessProviderType? dataAccessProviderType,
47156
Action<JetDbContextOptionsBuilder> jetOptionsAction)
48157
{
49158
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
50159
Check.NotEmpty(connectionString, nameof(connectionString));
51160

161+
if (dataAccessProviderFactory == null && dataAccessProviderType == null)
162+
{
163+
throw new ArgumentException($"One of the parameters {nameof(dataAccessProviderFactory)} and {nameof(dataAccessProviderType)} must not be null.");
164+
}
165+
52166
var extension = (JetOptionsExtension) GetOrCreateExtension(optionsBuilder)
53167
.WithConnectionString(connectionString);
54168

55-
extension = extension.WithDataAccessProviderFactory(dataAccessProviderFactory);
169+
extension = extension.WithDataAccessProviderFactory(
170+
dataAccessProviderFactory ?? JetFactory.Instance.GetDataAccessProviderFactory(dataAccessProviderType.Value));
56171

57172
((IDbContextOptionsBuilderInfrastructure) optionsBuilder).AddOrUpdateExtension(extension);
58173

@@ -63,6 +178,31 @@ private static DbContextOptionsBuilder UseJetCore(
63178
return optionsBuilder;
64179
}
65180

181+
#endregion
182+
183+
#region Connection
184+
185+
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
186+
/// <summary>
187+
/// Configures the context to connect to a Microsoft Jet database.
188+
/// </summary>
189+
/// <typeparam name="TContext"> The type of context to be configured. </typeparam>
190+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
191+
/// <param name="connection">
192+
/// An existing <see cref="DbConnection" /> to be used to connect to the database. If the connection is
193+
/// in the open state then EF will not open or close the connection. If the connection is in the closed
194+
/// state then EF will open and close the connection as needed.
195+
/// </param>
196+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
197+
/// <returns> The options builder so that further configuration can be chained. </returns>
198+
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
199+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
200+
[NotNull] DbConnection connection,
201+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
202+
where TContext : DbContext
203+
=> (DbContextOptionsBuilder<TContext>) UseJet(
204+
(DbContextOptionsBuilder) optionsBuilder, connection, jetOptionsAction);
205+
66206
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
67207
/// <summary>
68208
/// Configures the context to connect to a Microsoft Jet database.
@@ -91,14 +231,16 @@ public static DbContextOptionsBuilder UseJet(
91231

92232
if (jetConnection.DataAccessProviderFactory == null)
93233
{
94-
throw new ArgumentException($"The {nameof(connection)} parameter of type {nameof(JetConnection)} must have its {nameof(JetConnection.DataAccessProviderFactory)} property set to OdbcFactory or OleDbFactory.");
234+
var dataAccessProviderType = JetConnection.GetDataAccessProviderType(jetConnection.ConnectionString);
235+
jetConnection.DataAccessProviderFactory = JetFactory.Instance.GetDataAccessProviderFactory(dataAccessProviderType);
236+
jetConnection.Freeze();
95237
}
96238

97239
var extension = (JetOptionsExtension) GetOrCreateExtension(optionsBuilder)
98240
.WithConnection(connection);
99-
241+
100242
extension = extension.WithDataAccessProviderFactory(jetConnection.DataAccessProviderFactory);
101-
243+
102244
((IDbContextOptionsBuilderInfrastructure) optionsBuilder).AddOrUpdateExtension(extension);
103245

104246
ConfigureWarnings(optionsBuilder);
@@ -108,63 +250,8 @@ public static DbContextOptionsBuilder UseJet(
108250
return optionsBuilder;
109251
}
110252

253+
#endregion
111254

112-
/// <summary>
113-
/// Configures the context to connect to a Microsoft Jet database.
114-
/// </summary>
115-
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
116-
/// <param name="connectionString"> The connection string of the database to connect to. </param>
117-
/// <param name="dataAccessProviderFactory">A `OdbcFactory` or `OleDbFactory` object to be used for all
118-
/// data access operations by the Jet connection.</param>
119-
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
120-
/// <returns> The options builder so that further configuration can be chained. </returns>
121-
internal static DbContextOptionsBuilder UseJetWithoutPredefinedDataAccessProviderFactory<TContext>(
122-
[NotNull] this DbContextOptionsBuilder optionsBuilder,
123-
[NotNull] string connectionString,
124-
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
125-
where TContext : DbContext
126-
=> UseJetCore(optionsBuilder, connectionString, null, jetOptionsAction);
127-
128-
/// <summary>
129-
/// Configures the context to connect to a Microsoft Jet database.
130-
/// </summary>
131-
/// <typeparam name="TContext"> The type of context to be configured. </typeparam>
132-
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
133-
/// <param name="connectionString"> The connection string of the database to connect to. </param>
134-
/// <param name="dataAccessProviderFactory">A `OdbcFactory` or `OleDbFactory` object to be used for all
135-
/// data access operations by the Jet connection.</param>
136-
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
137-
/// <returns> The options builder so that further configuration can be chained. </returns>
138-
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
139-
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
140-
[NotNull] string connectionString,
141-
[NotNull] DbProviderFactory dataAccessProviderFactory,
142-
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
143-
where TContext : DbContext
144-
=> (DbContextOptionsBuilder<TContext>) UseJet(
145-
(DbContextOptionsBuilder) optionsBuilder, connectionString, dataAccessProviderFactory, jetOptionsAction);
146-
147-
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
148-
/// <summary>
149-
/// Configures the context to connect to a Microsoft Jet database.
150-
/// </summary>
151-
/// <typeparam name="TContext"> The type of context to be configured. </typeparam>
152-
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
153-
/// <param name="connection">
154-
/// An existing <see cref="DbConnection" /> to be used to connect to the database. If the connection is
155-
/// in the open state then EF will not open or close the connection. If the connection is in the closed
156-
/// state then EF will open and close the connection as needed.
157-
/// </param>
158-
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
159-
/// <returns> The options builder so that further configuration can be chained. </returns>
160-
public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
161-
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
162-
[NotNull] DbConnection connection,
163-
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
164-
where TContext : DbContext
165-
=> (DbContextOptionsBuilder<TContext>) UseJet(
166-
(DbContextOptionsBuilder) optionsBuilder, connection, jetOptionsAction);
167-
168255
private static JetOptionsExtension GetOrCreateExtension(DbContextOptionsBuilder optionsBuilder)
169256
=> optionsBuilder.Options.FindExtension<JetOptionsExtension>()
170257
?? new JetOptionsExtension();

src/EFCore.Jet/Metadata/Conventions/JetConventionSetBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static ConventionSet Build()
5656
var serviceProvider = new ServiceCollection()
5757
.AddEntityFrameworkJet()
5858
.AddDbContext<DbContext>((p, o) => o
59-
.UseJetWithoutPredefinedDataAccessProviderFactory<DbContext>(
59+
.UseJetWithoutPredefinedDataAccessProvider(
6060
JetConnection.GetConnectionString("Jet.accdb", DataAccessProviderType.Odbc))
6161
.UseInternalServiceProvider(p))
6262
.BuildServiceProvider();

src/System.Data.Jet/JetConnection.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class JetConnection : DbConnection, IDisposable, ICloneable
1010
{
1111
private ConnectionState _state;
1212
private string _connectionString;
13+
private bool _frozen;
1314

1415
internal DbConnection InnerConnection { get; private set; }
1516

@@ -175,6 +176,10 @@ public override string ConnectionString
175176
{
176177
if (State != ConnectionState.Closed)
177178
throw new InvalidOperationException(Messages.CannotChangePropertyValueInThisConnectionState(nameof(ConnectionString), State));
179+
180+
if (_frozen)
181+
throw new InvalidOperationException($"Cannot modify \"{nameof(ConnectionString)}\" property after the connection has been frozen.");
182+
178183
_connectionString = value;
179184
}
180185
}
@@ -298,11 +303,15 @@ public override void Open()
298303
return;
299304
if (string.IsNullOrWhiteSpace(_connectionString))
300305
throw new InvalidOperationException(Messages.PropertyNotInitialized(nameof(ConnectionString)));
301-
if (JetFactory == null)
302-
throw new InvalidOperationException(Messages.PropertyNotInitialized(nameof(DataAccessProviderFactory)));
303306
if (State != ConnectionState.Closed)
304307
throw new InvalidOperationException(Messages.CannotCallMethodInThisConnectionState(nameof(Open), ConnectionState.Closed, State));
305308

309+
if (JetFactory == null)
310+
{
311+
var dataAccessProviderType = GetDataAccessProviderType(ConnectionString);
312+
DataAccessProviderFactory = JetFactory.Instance.GetDataAccessProviderFactory(dataAccessProviderType);
313+
}
314+
306315
try
307316
{
308317
InnerConnection = InnerConnectionFactory.Instance.OpenConnection(
@@ -404,6 +413,12 @@ object ICloneable.Clone()
404413
return clone;
405414
}
406415

416+
public void Freeze()
417+
{
418+
if (!string.IsNullOrWhiteSpace(ConnectionString))
419+
_frozen = true;
420+
}
421+
407422
/// <summary>
408423
/// Clears the pool.
409424
/// </summary>

0 commit comments

Comments
 (0)