Skip to content

Commit f7ae775

Browse files
committed
Version 7.0.0
1 parent 47faf44 commit f7ae775

16 files changed

+130
-302
lines changed

EfSchemaCompare/CompareEfSql.cs

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,6 @@ public bool CompareEfWithDb(params DbContext[] dbContexts)
6060
return CompareEfWithDb(dbContexts[0].Database.GetDbConnection().ConnectionString, dbContexts);
6161
}
6262

63-
/// <summary>
64-
/// This will compare one or more DbContext against database pointed to the first DbContext
65-
/// using the DesignTimeServices type for T.
66-
/// </summary>
67-
/// <typeparam name="T">Must be the design time provider for the database provider you want to use, e.g. MySqlDesignTimeServices</typeparam>
68-
/// <param name="dbContexts">One or more dbContext instances to be compared with the database</param>
69-
/// <returns>true if any errors found, otherwise false</returns>
70-
public bool CompareEfWithDb<T>(params DbContext[] dbContexts) where T : IDesignTimeServices, new()
71-
{
72-
if (dbContexts == null) throw new ArgumentNullException(nameof(dbContexts));
73-
if (dbContexts.Length == 0)
74-
throw new ArgumentException("You must provide at least one DbContext instance.", nameof(dbContexts));
75-
var designTimeService = new T();
76-
return FinishRestOfCompare(dbContexts[0].Database.GetDbConnection().ConnectionString, dbContexts, designTimeService);
77-
}
78-
7963
/// <summary>
8064
/// This will compare one or more DbContext against database pointed to by the connectionString.
8165
/// </summary>
@@ -90,38 +74,15 @@ public bool CompareEfWithDb(string configOrConnectionString, params DbContext[]
9074
if (dbContexts.Length == 0)
9175
throw new ArgumentException("You must provide at least one DbContext instance.", nameof(dbContexts));
9276

93-
var designTimeService = dbContexts[0].GetDesignTimeService();
94-
return FinishRestOfCompare(GetConfigurationOrActualString(configOrConnectionString), dbContexts, designTimeService);
95-
}
96-
97-
98-
/// <summary>
99-
/// This will compare one or more DbContext against database pointed to by the connectionString
100-
/// using the DesignTimeServices type for T
101-
/// </summary>
102-
/// <typeparam name="T">Must be the design time provider for the database provider you want to use, e.g. MySqlDesignTimeServices</typeparam>
103-
/// <param name="configOrConnectionString">This should either be a
104-
/// connection string or the name of a connection string in the appsetting.json file.
105-
/// </param>
106-
/// <param name="dbContexts">One or more dbContext instances to be compared with the database</param>
107-
/// <returns>true if any errors found, otherwise false</returns>
108-
public bool CompareEfWithDb<T>(string configOrConnectionString, params DbContext[] dbContexts) where T: IDesignTimeServices, new()
109-
{
110-
if (configOrConnectionString == null) throw new ArgumentNullException(nameof(configOrConnectionString));
111-
if (dbContexts == null) throw new ArgumentNullException(nameof(dbContexts));
112-
if (dbContexts.Length == 0)
113-
throw new ArgumentException("You must provide at least one DbContext instance.", nameof(dbContexts));
114-
115-
var designTimeService = new T();
116-
return FinishRestOfCompare(GetConfigurationOrActualString(configOrConnectionString), dbContexts, designTimeService);
77+
return FinishRestOfCompare(GetConfigurationOrActualString(configOrConnectionString), dbContexts);
11778
}
11879

11980
//------------------------------------------------------
12081
//private methods
12182

122-
private bool FinishRestOfCompare(string connectionString, DbContext[] dbContexts, IDesignTimeServices designTimeService)
83+
private bool FinishRestOfCompare(string connectionString, DbContext[] dbContexts)
12384
{
124-
var databaseModel = GetDatabaseModelViaScaffolder(dbContexts, connectionString, designTimeService);
85+
var databaseModel = GetDatabaseModelViaScaffolder(dbContexts, connectionString);
12586
bool hasErrors = false;
12687
foreach (var context in dbContexts)
12788
{
@@ -138,12 +99,11 @@ private bool FinishRestOfCompare(string connectionString, DbContext[] dbContexts
13899
return hasErrors;
139100
}
140101

141-
private DatabaseModel GetDatabaseModelViaScaffolder(DbContext[] contexts, string connectionString, IDesignTimeServices designTimeService)
102+
private DatabaseModel GetDatabaseModelViaScaffolder(DbContext[] contexts, string connectionString)
142103
{
143-
var serviceProvider = designTimeService.GetDesignTimeProvider();
144-
var factory = (IDatabaseModelFactory) serviceProvider.GetService(typeof(IDatabaseModelFactory));
104+
var databaseFactory = contexts[0].GetDatabaseModelFactory();
145105

146-
var databaseModel = factory.Create(connectionString,
106+
var databaseModel = databaseFactory.Create(connectionString,
147107
new DatabaseModelFactoryOptions(new string[] { }, new string[] { }));
148108
RemoveAnyTableToIgnore(databaseModel, contexts);
149109
return databaseModel;

EfSchemaCompare/EfSchemaCompare.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
1717
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
1818
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
19+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0" />
1920
</ItemGroup>
2021

2122
<PropertyGroup>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2022 Jon P Smith, GitHub: JonPSmith, web: http://www.thereformedprogrammer.net/
2+
// Licensed under MIT license. See License.txt in the project root for license information.
3+
4+
using Microsoft.EntityFrameworkCore.Storage;
5+
using Microsoft.EntityFrameworkCore;
6+
using System;
7+
using Microsoft.EntityFrameworkCore.Infrastructure;
8+
using Microsoft.EntityFrameworkCore.Scaffolding;
9+
using Microsoft.EntityFrameworkCore.Diagnostics;
10+
using Microsoft.EntityFrameworkCore.Sqlite.Scaffolding.Internal;
11+
using Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal;
12+
using Npgsql.EntityFrameworkCore.PostgreSQL.Scaffolding.Internal;
13+
14+
namespace EfSchemaCompare.Internal;
15+
16+
internal static class DatabaseModelFinder
17+
{
18+
private const string SqlServerProviderName = "Microsoft.EntityFrameworkCore.SqlServer";
19+
private const string SqliteProviderName = "Microsoft.EntityFrameworkCore.Sqlite";
20+
private const string PostgresSqlProviderName = "Npgsql.EntityFrameworkCore.PostgreSQL";
21+
22+
public static IDatabaseModelFactory GetDatabaseModelFactory(this DbContext context)
23+
{
24+
25+
var providerName = context.Database.ProviderName;
26+
27+
var logger = context.GetService<IDiagnosticsLogger<DbLoggerCategory.Scaffolding>>();
28+
29+
if (providerName == SqlServerProviderName)
30+
return new SqlServerDatabaseModelFactory(logger);
31+
if (providerName == SqliteProviderName)
32+
{
33+
var typeMapper = context.GetService<IRelationalTypeMappingSource>();
34+
return new SqliteDatabaseModelFactory(logger, typeMapper);
35+
}
36+
if (providerName == PostgresSqlProviderName)
37+
return new NpgsqlDatabaseModelFactory(logger);
38+
39+
throw new InvalidOperationException("Your database provider isn't supported by the EfCore.SchemaCompare library. " +
40+
"Please provide an issue about the database type you would like and I may be able to add it.");
41+
}
42+
}

EfSchemaCompare/Internal/DesignProvider.cs

Lines changed: 0 additions & 74 deletions
This file was deleted.

README.md

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ The EfCore.SchemaCompare library (shortened to EfSchemaCompare in the documentat
1717
2. [List of limitations](#List-of-limitations)
1818
3. [Introduction to how EfSchemaCompare works](#Introduction-to-how-EfSchemaCompare-works)
1919
4. [How to use EfSchemaCompare](#How-to-use-EfSchemaCompare)
20+
5. [Different parameters to the `CompareEfWithDb` method](#different-parameters-to-the-compareefwithdb-method)
2021
5. [Understanding the error messages](#Understanding-the-error-messages)
2122
6. [How to suppress certain error messages](#How-to-suppress-certain-error-messages)
2223
7. [Other configuration options](#Other-configuration-options)
@@ -54,8 +55,9 @@ The EfCore.SchemaCompare library (shortened to EfSchemaCompare in the documentat
5455
## List of limitations
5556

5657
- The EF Core's scaffolder doesn't read in any index on the foreign key (the scaffolder assumes EF Core will do that by default). That means I can't check that there is an index on a foreign key.
57-
- Cannot correctly check Table-per-Type classes beacause EF Core doesn't currently hold that data. This is tracked by [Ef Core #19811](https://github.com/dotnet/efcore/issues/19811).
58-
- Cannot compare database tables/columns using InvariantCultureIgnoreCase. That is a EF Core 5 limitation.
58+
- Cannot correctly check Table-per-Type or Table-per-Class classes because EF Core doesn't currently hold that data. This is tracked by [Ef Core #19811](https://github.com/dotnet/efcore/issues/19811).
59+
- Cannot compare database tables/columns using InvariantCultureIgnoreCase. That is a EF Core 5+ limitation.
60+
- At the moment this library only supports SQL Server, Sqlite and PostgresSql.
5961

6062
The following are things I haven't bothered to check.
6163

@@ -133,29 +135,6 @@ public void CompareBookThenOrderAgainstBookOrderDatabaseViaAppSettings()
133135
}
134136
```
135137

136-
### Using with database provider not installed in `EfCore.SchemaCompare` library
137-
138-
The `EfCore.SchemaCompare` library only contains the SqlServer and Sqlite database providers. But if you want to run the compare with a specific database provider you can do that using the version with takes in a `IDesignTimeServices` for your database provider which contains the reverse engineering feature. For instance if you wanted to check a PostgreSql database you would use the following code shown below.
139-
140-
```c#
141-
[Fact]
142-
public void TestCompareEfSqlPostgreSql()
143-
{
144-
//SETUP
145-
using (var context = new BookContext(_options))
146-
{
147-
var comparer = new CompareEfSql();
148-
149-
//ATTEMPT
150-
//This will use the database provider design time type you gave to get the database information
151-
var hasErrors = comparer.CompareEfWithDb<NpgsqlDesignTimeServices>(context));
152-
153-
//VERIFY
154-
hasErrors.ShouldBeFalse(comparer.GetAllErrors);
155-
}
156-
}
157-
```
158-
159138
## Understanding the error messages
160139

161140
The `comparer.GetAllErrors` property will return a string with each error separated by the `Environment.NewLine` string. Below is an example of an error

ReleaseNotes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release notes
22

3+
## 7.0.0
4+
5+
- Updated to EF Core 7.0
6+
37
## 6.0.0
48

59
- Updated to EF Core 6.0 (thanks to Wade Baglin, GitHub @pleb)

Test/UnitTests/ComparerBooksExamples.cs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -92,41 +92,6 @@ public void CompareSuppressViaViaAddIgnoreCompareLog()
9292
hasErrors.ShouldBeFalse(comparer.GetAllErrors);
9393
}
9494

95-
[Fact]
96-
public void CompareViaType()
97-
{
98-
//SETUP
99-
var options = this.CreateUniqueClassOptions<BookContext>();
100-
using var context = new BookContext(options);
101-
context.Database.EnsureClean();
102-
103-
var comparer = new CompareEfSql();
104-
105-
//ATTEMPT
106-
var hasErrors = comparer.CompareEfWithDb<SqlServerDesignTimeServices>(context);
107-
108-
//VERIFY
109-
hasErrors.ShouldBeFalse(comparer.GetAllErrors);
110-
}
111-
112-
[Fact]
113-
public void CompareViaTypeWithConnection()
114-
{
115-
//SETUP
116-
var options = this.CreateUniqueClassOptions<BookContext>();
117-
using var context = new BookContext(options);
118-
context.Database.EnsureClean();
119-
120-
var comparer = new CompareEfSql();
121-
122-
//ATTEMPT
123-
var hasErrors =
124-
comparer.CompareEfWithDb<SqlServerDesignTimeServices>(context.Database.GetConnectionString(), context);
125-
126-
//VERIFY
127-
hasErrors.ShouldBeFalse(comparer.GetAllErrors);
128-
}
129-
13095
[Fact]
13196
public void CompareBadConnection()
13297
{

Test/UnitTests/OldTestSupportIssueTests/Issue012Tests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ public void TestTwoTablesWithSameNameButDifferentSchemas()
3939
//SETUP
4040
using (var context = new Issue012DbContext(_options))
4141
{
42-
var dtService = context.GetDesignTimeService();
43-
var serviceProvider = dtService.GetDesignTimeProvider();
44-
var factory = serviceProvider.GetService<IDatabaseModelFactory>();
42+
var factory = context.GetDatabaseModelFactory();
4543
var database = factory.Create(_connectionString,
4644
new DatabaseModelFactoryOptions(new string[] { }, new string[] { }));
4745

Test/UnitTests/Stage1ComparerBooksDiff.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ public void CompareSelfTestEfCoreContext()
3939
//SETUP
4040
using (var context = new BookContext(_options))
4141
{
42-
var dtService = context.GetDesignTimeService();
43-
var serviceProvider = dtService.GetDesignTimeProvider();
44-
var factory = serviceProvider.GetService<IDatabaseModelFactory>();
42+
var factory = context.GetDatabaseModelFactory();
4543
var database = factory.Create(_connectionString,
4644
new DatabaseModelFactoryOptions(new string[] { }, new string[] { }));
4745

Test/UnitTests/Stage1ComparerMyEntityDiff.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ public Stage1ComparerMyEntityDiff(ITestOutputHelper output)
3030
{
3131
_output = output;
3232

33-
var serviceProvider = new SqlServerDesignTimeServices().GetDesignTimeProvider();
34-
var factory = serviceProvider.GetService<IDatabaseModelFactory>();
33+
3534

3635
var options = this.CreateUniqueClassOptions<MyEntityDbContext>(
3736
builder => builder.ReplaceService<IModelCacheKeyFactory, MyEntityModelCacheKeyFactory>());
3837
using (var context = new MyEntityDbContext(options, MyEntityDbContext.Configs.NormalTable))
3938
{
4039
context.Database.EnsureClean();
40+
var factory = context.GetDatabaseModelFactory();
4141
var connectionString = context.Database.GetDbConnection().ConnectionString;
4242
databaseModel = factory.Create(connectionString,
4343
new DatabaseModelFactoryOptions(new string[] { }, new string[] { }));

Test/UnitTests/Stage2ComparerMyEntityDiff.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,12 @@ public Stage2ComparerMyEntityDiff(ITestOutputHelper output)
3333
_output = output;
3434
var options = this
3535
.CreateUniqueClassOptions<MyEntityDbContext>();
36-
var serviceProvider = new SqlServerDesignTimeServices().GetDesignTimeProvider();
37-
var factory = serviceProvider.GetService<IDatabaseModelFactory>();
3836

3937
using (var context = new MyEntityDbContext(options, MyEntityDbContext.Configs.NormalTable))
4038
{
4139
var connectionString = context.Database.GetDbConnection().ConnectionString;
4240
context.Database.EnsureClean();
43-
41+
var factory = context.GetDatabaseModelFactory();
4442
_databaseModel = factory.Create(connectionString,
4543
new DatabaseModelFactoryOptions(new string[] { }, new string[] { }));
4644
}
@@ -110,9 +108,7 @@ public void ExtraIndexConstaint()
110108
builder => builder.ReplaceService<IModelCacheKeyFactory, MyEntityModelCacheKeyFactory>());
111109
using (var context = new MyEntityDbContext(options, MyEntityDbContext.Configs.HasIndex))
112110
{
113-
var dtService = context.GetDesignTimeService();
114-
var serviceProvider = dtService.GetDesignTimeProvider();
115-
var factory = serviceProvider.GetService<IDatabaseModelFactory>();
111+
var factory = context.GetDatabaseModelFactory();
116112
var connectionString = context.Database.GetDbConnection().ConnectionString;
117113

118114
context.Database.EnsureClean();

0 commit comments

Comments
 (0)