Skip to content

Commit 4158e51

Browse files
committed
Add ODBC and OLE DB specific projects/packages.
1 parent 7a6e90b commit 4158e51

9 files changed

+289
-8
lines changed

Directory.Build.props

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
<PropertyGroup>
66
<Product>EntityFrameworkCore.Jet</Product>
7-
<Description>Jet (Microsoft Access mdb or accdb files) provider for Entity Framework Core (EFCore)</Description>
87
<Authors>Laurents Meyer, Bubi</Authors>
98
<Company>Bubi</Company>
109
<Copyright>Copyright © 2017-2020 Bubi</Copyright>
@@ -13,7 +12,7 @@
1312
<DebugType>portable</DebugType>
1413
<IsPackable>False</IsPackable>
1514
<!-- <PackageReleaseNotes>TODO</PackageReleaseNotes> -->
16-
<PackageTags>Entity Framework Core Jet;Entity Framework Core Access;Entity Framework Core MS Access;entity-framework-core-jet;entity-framework-core-access;entity-framework-core-msaccess;EF Jet;EF Access;EF MS Access;Data;O/RM;EntityFramework;EntityFrameworkCore;EFCore;Jet;Access;MS Access</PackageTags>
15+
<PackageTags>Entity Framework Core Jet;Entity Framework Core Access;Entity Framework Core MS Access;entity-framework-core-jet;entity-framework-core-access;entity-framework-core-msaccess;EF Jet;EF Access;EF MS Access;Data;O/RM;EntityFramework;EntityFrameworkCore;EFCore;Jet;Access;MS Access;ACE</PackageTags>
1716
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
1817
<PackageProjectUrl>https://github.com/bubibubi/EntityFrameworkCore.Jet</PackageProjectUrl>
1918
<!-- <PackageIconUrl>TODO</PackageIconUrl> -->

src/Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131
<IncludeSymbols>true</IncludeSymbols>
3232
<EmbedUntrackedSources>true</EmbedUntrackedSources>
3333
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
34+
<MinClientVersion>3.6</MinClientVersion>
3435
</PropertyGroup>
3536
</Project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<Description>Explicit ODBC support for Jet/ACE database provider for Entity Framework Core (Microsoft Access MDB/ACCDB files).</Description>
5+
<TargetFramework>$(DefaultNetStandardTargetFramework)</TargetFramework>
6+
<AssemblyName>EntityFrameworkCore.Jet.Odbc</AssemblyName>
7+
<RootNamespace>EntityFrameworkCore.Jet</RootNamespace>
8+
<PackageTags>$(PackageTags);ODBC;System.Data.Odbc</PackageTags>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<Compile Include="..\Shared\*.cs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\EFCore.Jet\EFCore.Jet.csproj" PrivateAssets="contentfiles;build" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<PackageReference Include="System.Data.Odbc" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System;
4+
using System.Data.Jet;
5+
using System.Data.Odbc;
6+
using EntityFrameworkCore.Jet.Infrastructure;
7+
using JetBrains.Annotations;
8+
using EntityFrameworkCore.Jet.Utilities;
9+
10+
// ReSharper disable once CheckNamespace
11+
namespace Microsoft.EntityFrameworkCore
12+
{
13+
/// <summary>
14+
/// Jet specific ODBC extension methods for <see cref="DbContextOptionsBuilder" />.
15+
/// </summary>
16+
public static class JetOdbcDbContextOptionsBuilderExtensions
17+
{
18+
#region Connection String
19+
20+
/// <summary>
21+
/// Configures the context to connect to a Microsoft Jet database using ODBC.
22+
/// </summary>
23+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
24+
/// <param name="fileNameOrConnectionString"> The file name or ODBC connection string of the database to connect
25+
/// to. In case the connection string does not specify an Access driver (ODBC), the highest version of all
26+
/// compatible installed ones is being used. </param>
27+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
28+
/// <returns> The options builder so that further configuration can be chained. </returns>
29+
public static DbContextOptionsBuilder<TContext> UseJetOdbc<TContext>(
30+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
31+
[NotNull] string fileNameOrConnectionString,
32+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
33+
where TContext : DbContext
34+
=> optionsBuilder.UseJet(fileNameOrConnectionString, DataAccessProviderType.Odbc, jetOptionsAction);
35+
36+
/// <summary>
37+
/// Configures the context to connect to a Microsoft Jet database using ODBC.
38+
/// </summary>
39+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
40+
/// <param name="fileNameOrConnectionString"> The file name or ODBC connection string of the database to connect
41+
/// to. In case the connection string does not specify an Access driver (ODBC), the highest version of all
42+
/// compatible installed ones is being used. </param>
43+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
44+
/// <returns> The options builder so that further configuration can be chained. </returns>
45+
public static DbContextOptionsBuilder UseJetOdbc(
46+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
47+
[NotNull] string fileNameOrConnectionString,
48+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
49+
=> optionsBuilder.UseJet(fileNameOrConnectionString, DataAccessProviderType.Odbc, jetOptionsAction);
50+
51+
#endregion
52+
53+
#region Connection
54+
55+
/// <summary>
56+
/// Configures the context to connect to a Microsoft Jet database using ODBC.
57+
/// </summary>
58+
/// <typeparam name="TContext"> The type of context to be configured. </typeparam>
59+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
60+
/// <param name="connection">
61+
/// An existing <see cref="OdbcConnection" /> to be used to connect to the database. If the connection is in
62+
/// the open state then EF will not open or close the connection. If the connection is in the closed state
63+
/// then EF will open and close the connection as needed.
64+
/// </param>
65+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
66+
/// <returns> The options builder so that further configuration can be chained. </returns>
67+
public static DbContextOptionsBuilder<TContext> UseJetOdbc<TContext>(
68+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
69+
[NotNull] OdbcConnection connection,
70+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
71+
where TContext : DbContext
72+
{
73+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
74+
Check.NotNull(connection, nameof(connection));
75+
76+
return optionsBuilder.UseJet(connection, jetOptionsAction);
77+
}
78+
79+
/// <summary>
80+
/// Configures the context to connect to a Microsoft Jet database using ODBC.
81+
/// </summary>
82+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
83+
/// <param name="connection">
84+
/// An existing <see cref="OdbcConnection" /> to be used to connect to the database. If the connection is in
85+
/// the open state then EF will not open or close the connection. If the connection is in the closed state
86+
/// then EF will open and close the connection as needed.
87+
/// </param>
88+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
89+
/// <returns> The options builder so that further configuration can be chained. </returns>
90+
public static DbContextOptionsBuilder UseJetOdbc(
91+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
92+
[NotNull] OdbcConnection connection,
93+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
94+
{
95+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
96+
Check.NotNull(connection, nameof(connection));
97+
98+
return optionsBuilder.UseJet(connection, jetOptionsAction);
99+
}
100+
101+
#endregion
102+
}
103+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<Description>Explicit OLE DB support for Jet/ACE database provider for Entity Framework Core (Microsoft Access MDB/ACCDB files).</Description>
5+
<TargetFramework>$(DefaultNetStandardTargetFramework)</TargetFramework>
6+
<AssemblyName>EntityFrameworkCore.Jet.OleDb</AssemblyName>
7+
<RootNamespace>EntityFrameworkCore.Jet</RootNamespace>
8+
<PackageTags>$(PackageTags);OLE DB;OLEDB;System.Data.OleDb</PackageTags>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<Compile Include="..\Shared\*.cs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\EFCore.Jet\EFCore.Jet.csproj" PrivateAssets="contentfiles;build" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<PackageReference Include="System.Data.OleDb" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System;
4+
using System.Data.Jet;
5+
using System.Data.OleDb;
6+
using EntityFrameworkCore.Jet.Infrastructure;
7+
using JetBrains.Annotations;
8+
using EntityFrameworkCore.Jet.Utilities;
9+
10+
// ReSharper disable once CheckNamespace
11+
namespace Microsoft.EntityFrameworkCore
12+
{
13+
/// <summary>
14+
/// Jet specific OLE DB extension methods for <see cref="DbContextOptionsBuilder" />.
15+
/// </summary>
16+
public static class JetOleDbDbContextOptionsBuilderExtensions
17+
{
18+
#region Connection String
19+
20+
/// <summary>
21+
/// Configures the context to connect to a Microsoft Jet database using OLE DB.
22+
/// </summary>
23+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
24+
/// <param name="fileNameOrConnectionString"> The file name or OLE DB connection string of the database to connect
25+
/// to. In case the connection string does not specify an Jet/ACE provider (OLE DB), the highest version of all
26+
/// compatible installed ones is being used. </param>
27+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
28+
/// <returns> The options builder so that further configuration can be chained. </returns>
29+
public static DbContextOptionsBuilder<TContext> UseJetOleDb<TContext>(
30+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
31+
[NotNull] string fileNameOrConnectionString,
32+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
33+
where TContext : DbContext
34+
=> optionsBuilder.UseJet(fileNameOrConnectionString, DataAccessProviderType.OleDb, jetOptionsAction);
35+
36+
/// <summary>
37+
/// Configures the context to connect to a Microsoft Jet database using OLE DB.
38+
/// </summary>
39+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
40+
/// <param name="fileNameOrConnectionString"> The file name or OLE DB connection string of the database to connect
41+
/// to. In case the connection string does not specify an Jet/ACE provider (OLE DB), the highest version of all
42+
/// compatible installed ones is being used. </param>
43+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
44+
/// <returns> The options builder so that further configuration can be chained. </returns>
45+
public static DbContextOptionsBuilder UseJetOleDb(
46+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
47+
[NotNull] string fileNameOrConnectionString,
48+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
49+
=> optionsBuilder.UseJet(fileNameOrConnectionString, DataAccessProviderType.OleDb, jetOptionsAction);
50+
51+
#endregion
52+
53+
#region Connection
54+
55+
/// <summary>
56+
/// Configures the context to connect to a Microsoft Jet database using OLE DB.
57+
/// </summary>
58+
/// <typeparam name="TContext"> The type of context to be configured. </typeparam>
59+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
60+
/// <param name="connection">
61+
/// An existing <see cref="OleDbConnection" /> to be used to connect to the database. If the connection is in
62+
/// the open state then EF will not open or close the connection. If the connection is in the closed state
63+
/// then EF will open and close the connection as needed.
64+
/// </param>
65+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
66+
/// <returns> The options builder so that further configuration can be chained. </returns>
67+
public static DbContextOptionsBuilder<TContext> UseJetOleDb<TContext>(
68+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
69+
[NotNull] OleDbConnection connection,
70+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
71+
where TContext : DbContext
72+
{
73+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
74+
Check.NotNull(connection, nameof(connection));
75+
76+
return optionsBuilder.UseJet(connection, jetOptionsAction);
77+
}
78+
79+
/// <summary>
80+
/// Configures the context to connect to a Microsoft Jet database using OLE DB.
81+
/// </summary>
82+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
83+
/// <param name="connection">
84+
/// An existing <see cref="OleDbConnection" /> to be used to connect to the database. If the connection is in
85+
/// the open state then EF will not open or close the connection. If the connection is in the closed state
86+
/// then EF will open and close the connection as needed.
87+
/// </param>
88+
/// <param name="jetOptionsAction">An optional action to allow additional Jet specific configuration.</param>
89+
/// <returns> The options builder so that further configuration can be chained. </returns>
90+
public static DbContextOptionsBuilder UseJetOleDb(
91+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
92+
[NotNull] OleDbConnection connection,
93+
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
94+
{
95+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
96+
Check.NotNull(connection, nameof(connection));
97+
98+
return optionsBuilder.UseJet(connection, jetOptionsAction);
99+
}
100+
101+
#endregion
102+
}
103+
}

src/EFCore.Jet/EFCore.Jet.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4+
<Description>Jet/ACE database provider for Entity Framework Core (Microsoft Access MDB/ACCDB files).</Description>
45
<TargetFrameworks>$(DefaultNetStandardTargetFramework);netcoreapp2.1;net461</TargetFrameworks>
56
<RootNamespace>EntityFrameworkCore.Jet</RootNamespace>
67
<AssemblyName>EntityFrameworkCore.Jet</AssemblyName>

src/EFCore.Jet/Extensions/JetDbContextOptionsBuilderExtensions.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
3737
[NotNull] string fileNameOrConnectionString,
3838
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
3939
where TContext : DbContext
40-
=> (DbContextOptionsBuilder<TContext>) UseJet((DbContextOptionsBuilder) optionsBuilder, fileNameOrConnectionString, jetOptionsAction);
40+
{
41+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
42+
Check.NotEmpty(fileNameOrConnectionString, nameof(fileNameOrConnectionString));
43+
44+
return (DbContextOptionsBuilder<TContext>) UseJet((DbContextOptionsBuilder) optionsBuilder, fileNameOrConnectionString, jetOptionsAction);
45+
}
4146

4247
/// <summary>
4348
/// Configures the context to connect to a Microsoft Jet database.
@@ -219,8 +224,13 @@ public static DbContextOptionsBuilder<TContext> UseJet<TContext>(
219224
[NotNull] DbConnection connection,
220225
[CanBeNull] Action<JetDbContextOptionsBuilder> jetOptionsAction = null)
221226
where TContext : DbContext
222-
=> (DbContextOptionsBuilder<TContext>) UseJet(
227+
{
228+
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
229+
Check.NotNull(connection, nameof(connection));
230+
231+
return (DbContextOptionsBuilder<TContext>) UseJet(
223232
(DbContextOptionsBuilder) optionsBuilder, connection, jetOptionsAction);
233+
}
224234

225235
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
226236
/// <summary>

src/System.Data.Jet/JetFactory.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ namespace System.Data.Jet
88
/// </summary>
99
public class JetFactory : DbProviderFactory
1010
{
11+
public static readonly Version MinimumRequiredOdbcVersion = new Version(5, 0, 0);
12+
public static readonly Version MinimumRequiredOleDbVersion = new Version(5, 0, 0);
1113
public static readonly JetFactory Instance = new JetFactory(null, null);
1214

1315
public JetConnection Connection { get; }
@@ -117,26 +119,42 @@ public virtual DbProviderFactory GetDataAccessProviderFactory(DataAccessProvider
117119
{
118120
try
119121
{
120-
return (DbProviderFactory) Type.GetType("System.Data.OleDb.OleDbFactory, System.Data.OleDb")
122+
var type = Type.GetType("System.Data.OleDb.OleDbFactory, System.Data.OleDb");
123+
var version = type.Assembly.GetName().Version;
124+
125+
if (version < MinimumRequiredOleDbVersion)
126+
{
127+
throw new TypeLoadException($"The referenced version '{version}' of 'System.Data.OleDb' is lower than the minimum required version {MinimumRequiredOleDbVersion}.");
128+
}
129+
130+
return (DbProviderFactory) type
121131
.GetField("Instance", BindingFlags.Static | BindingFlags.Public)
122132
.GetValue(null);
123133
}
124134
catch (Exception e)
125135
{
126-
throw new TypeLoadException("To use OLE DB in conjunction with Jet, please reference the \"System.Data.OleDb\" NuGet package.", e);
136+
throw new TypeLoadException("To use OLE DB in conjunction with Jet, please reference the 'System.Data.OleDb' (version >= 5.0.0) NuGet package.", e);
127137
}
128138
}
129139
else
130140
{
131141
try
132142
{
133-
return (DbProviderFactory) Type.GetType("System.Data.Odbc.OdbcFactory, System.Data.Odbc")
143+
var type = Type.GetType("System.Data.Odbc.OdbcFactory, System.Data.Odbc");
144+
var version = type.Assembly.GetName().Version;
145+
146+
if (version < MinimumRequiredOdbcVersion)
147+
{
148+
throw new TypeLoadException($"The referenced version '{version}' of 'System.Data.Odbc' is lower than the minimum required version {MinimumRequiredOdbcVersion}.");
149+
}
150+
151+
return (DbProviderFactory) type
134152
.GetField("Instance", BindingFlags.Static | BindingFlags.Public)
135153
.GetValue(null);
136154
}
137155
catch (Exception e)
138156
{
139-
throw new TypeLoadException("To use ODBC in conjunction with Jet, please reference the \"System.Data.Odbc\" NuGet package.", e);
157+
throw new TypeLoadException("To use ODBC in conjunction with Jet, please reference the 'System.Data.Odbc' (version >= 5.0.0) NuGet package.", e);
140158
}
141159
}
142160
}

0 commit comments

Comments
 (0)