Skip to content

Commit 3cadf80

Browse files
committed
Version 8.0.0-rc2-0002 - for user testing
1 parent fa1caeb commit 3cadf80

File tree

5 files changed

+94
-88
lines changed

5 files changed

+94
-88
lines changed

EfSchemaCompare/EfSchemaCompare.csproj

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,33 @@
55
<GenerateDocumentationFile>true</GenerateDocumentationFile>
66
</PropertyGroup>
77

8-
98
<ItemGroup>
10-
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-rc.1.23419.6">
11-
<PrivateAssets>all</PrivateAssets>
12-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13-
</PackageReference>
14-
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0-rc.1.23419.6" />
15-
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.1.23419.6" />
16-
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.1.23419.6" />
17-
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0-rc.1.23419.4" />
9+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-rc.2.23480.1">
10+
<PrivateAssets>all</PrivateAssets>
11+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
12+
</PackageReference>
13+
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0-rc.2.23480.1" />
14+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.2.23480.1" />
15+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.2.23480.1" />
16+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0-rc.2.23479.6" />
1817
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
19-
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.1" />
18+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
2019
</ItemGroup>
2120

2221
<PropertyGroup>
2322
<PackageId>EfCore.SchemaCompare</PackageId>
24-
<PackageVersion>8.0.0-rc1-0001</PackageVersion>
23+
<PackageVersion>8.0.0-rc2-0002</PackageVersion>
2524
<Version>8.0.0</Version>
2625
<AssemblyVersion>8.0.0</AssemblyVersion>
2726
<FileVersion>8.0.0</FileVersion>
2827
<Authors>Jon P Smith</Authors>
2928
<Description>Useful tool if you are changing the schema of your database's schema outside of EF Core' migrations, say by using SQL change scripts. See readme file on github.</Description>
3029
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
3130
<PackageReleaseNotes>
32-
Fix to issue #21, but now catches "Not In Database" errors, as seen in issue #25
31+
- Supports .NET 8-rc.2 - please try this version and report any problems
32+
- NEW FEATURE: Now compares all EF Core database providers, but some database providers may show incorrect match errors
33+
- BREAKING CHANGE: You need to add the Microsoft.EntityFrameworkCore.Design NuGet to your
34+
- Bug Fix: Fix to issue #21
3335
</PackageReleaseNotes>
3436
<Copyright>Copyright (c) 2020 Jon P Smith. Licenced under MIT licence</Copyright>
3537
<PackageTags>Entity Framework Core, Database</PackageTags>
Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,76 @@
11
// Copyright (c) 2022 Jon P Smith, GitHub: JonPSmith, web: http://www.thereformedprogrammer.net/
22
// Licensed under MIT license. See License.txt in the project root for license information.
33

4-
using Microsoft.EntityFrameworkCore.Storage;
5-
using Microsoft.EntityFrameworkCore;
64
using System;
7-
using System.Diagnostics.CodeAnalysis;
5+
using System.IO;
86
using System.Linq;
97
using System.Reflection;
10-
using Microsoft.EntityFrameworkCore.Infrastructure;
8+
using Microsoft.EntityFrameworkCore;
119
using Microsoft.EntityFrameworkCore.Scaffolding;
12-
using Microsoft.EntityFrameworkCore.Diagnostics;
10+
using Microsoft.Extensions.DependencyInjection;
1311

1412
namespace EfSchemaCompare.Internal;
1513

1614
internal static class DatabaseModelFinder
1715
{
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-
16+
/// <summary>
17+
/// This obtains the <see cref="DatabaseModelFactory"/> which is needed to find the schema of a database.
18+
/// Thanks to GitHub @bgrauer-atacom and @lweberprb for suggesting that this library could support extra database providers.
19+
/// See https://github.com/JonPSmith/EfCore.SchemaCompare/pull/26 for more on this
20+
/// </summary>
21+
/// <param name="context"></param>
22+
/// <returns></returns>
2223
public static IDatabaseModelFactory GetDatabaseModelFactory(this DbContext context)
2324
{
24-
var providerName = context.Database.ProviderName;
25-
26-
var logger = context.GetService<IDiagnosticsLogger<DbLoggerCategory.Scaffolding>>();
25+
// REVIEW: According to my understanding the assembly is where the DBContext is
26+
var assembly = context.GetType().Assembly;
2727

28-
var providerAssembly = Assembly.Load(providerName!);
29-
var factoryType = providerAssembly.ExportedTypes.First(x => x.BaseType == typeof(DatabaseModelFactory));
30-
var typeMapper = context.GetService<IRelationalTypeMappingSource>();
28+
// REVIEW: This is not the same behaviour as in the CLI but we don't know the real startup project. Using the test project
29+
// assembly as stratup assembly hand enables the possibility to define design services inside of the test project for test purposes.
30+
var startupAssembly = Assembly.GetEntryAssembly() ?? assembly;
3131

32-
object factoryObject;
33-
switch (providerName)
32+
try
3433
{
35-
case SqliteProviderName:
36-
factoryObject = Activator.CreateInstance(factoryType, logger, typeMapper);
37-
break;
38-
case SqlServerProviderName:
39-
factoryObject = Activator.CreateInstance(factoryType, logger, typeMapper);
40-
break;
41-
case PostgresSqlProviderName:
42-
factoryObject = Activator.CreateInstance(factoryType, logger);
43-
break;
44-
default:
45-
// This is not a known provider. Try creating the factory anyhow and throw if it fails
46-
factoryObject = TryCreateUnknownFactory(factoryType, logger, providerName);
47-
break;
48-
}
34+
// REVIEW: In my case, the assembly was loaded correct. Unsure if this works in all cases.
35+
var designAssembly = Assembly.Load("Microsoft.EntityFrameworkCore.Design");
4936

50-
if (factoryObject is IDatabaseModelFactory factory)
51-
return factory;
37+
var reportHandlerType = designAssembly.GetType("Microsoft.EntityFrameworkCore.Design.OperationReportHandler")
38+
?? throw new InvalidOperationException("Unable to create an 'OperationReportHandler' instance. Are you using a supported EntityFrameworkCore version?");
39+
// TODO: Maybe implement handler actions for logging purposes?
40+
var reportHandler = Activator.CreateInstance(reportHandlerType, null, null, null, null);
5241

53-
ThrowException(providerName);
54-
return (IDatabaseModelFactory) new object();
55-
}
42+
var reporterType = designAssembly.GetType("Microsoft.EntityFrameworkCore.Design.Internal.OperationReporter")
43+
?? throw new InvalidOperationException("Unable to create an 'OperationReporter' instance. Are you using a supported EntityFrameworkCore version?");
44+
var reporter = Activator.CreateInstance(reporterType, reportHandler);
5645

57-
private static object TryCreateUnknownFactory(Type factoryType,
58-
IDiagnosticsLogger<DbLoggerCategory.Scaffolding> logger, string providerName)
59-
{
60-
try
61-
{
62-
return Activator.CreateInstance(factoryType);
46+
var serviceBuilderType = designAssembly.GetType($"Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder")
47+
?? throw new InvalidOperationException("Unable to create an 'DesignTimeServicesBuilder' instance. Are you using a supported EntityFrameworkCore version?");
48+
var serviceBuilder = Activator.CreateInstance(serviceBuilderType, assembly, startupAssembly, reporter, Array.Empty<string>());
49+
50+
var serviceProvider = (IServiceProvider?)serviceBuilderType.GetMethods()
51+
.Where(x => {
52+
if (x.Name != "Build")
53+
{
54+
return false;
55+
}
56+
var pars = x.GetParameters();
57+
if (pars.Length != 1)
58+
{
59+
return false;
60+
}
61+
return pars[0].ParameterType.Name == "DbContext";
62+
})
63+
.FirstOrDefault()
64+
?.Invoke(serviceBuilder, new object[] { context })
65+
?? throw new InvalidOperationException("Unable to bild design time service provider. Are you using a supported EntityFrameworkCore version?"); ;
66+
67+
return serviceProvider.GetRequiredService<IDatabaseModelFactory>();
6368
}
64-
catch
69+
catch (FileNotFoundException ex)
6570
{
66-
try
67-
{
68-
return Activator.CreateInstance(factoryType, logger);
69-
}
70-
catch
71-
{
72-
ThrowException(providerName);
73-
}
71+
throw new InvalidOperationException($"Your startup project '{startupAssembly.GetName()}' doesn't reference " +
72+
"Microsoft.EntityFrameworkCore.Design. This package is required for the SchemaCompare to work. " +
73+
"Ensure your startup project is correct, install the package, and try again.", ex);
7474
}
75-
76-
return null;
77-
}
78-
79-
[DoesNotReturn]
80-
private static void ThrowException(string providerName)
81-
{
82-
throw new InvalidOperationException(
83-
$"It could not find the correct EF Core code to support the {providerName} database.");
8475
}
8576
}

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# EfCore.SchemaCompare
22

3-
If you are changing the schema of your database's schema outside of EF Core' migrations, say by using SQL change scripts, then this library can quickly tell you if the a specific database schema and EF Core's `Model` of the database are in step.
3+
If you are changing the schema of your database's schema outside of EF Core' migrations, say by using SQL change scripts, then this library can quickly tell you if the a specific database schema and EF Core's `Model` of the database are in step. Versions below 8 this library
44

55
The first number in the version number of this library defines what version of NET framework it works for. e.g.
66

@@ -11,17 +11,26 @@ The EfCore.SchemaCompare library (shortened to EfSchemaCompare in the documentat
1111

1212
**TABLE OF CONTENT**
1313

14-
1. [What does EfSchemaCompare check?](#what-does-EfSchemaCompare-check)
15-
2. [List of limitations](#List-of-limitations)
16-
3. [Introduction to how EfSchemaCompare works](#Introduction-to-how-EfSchemaCompare-works)
17-
4. [How to use EfSchemaCompare](#How-to-use-EfSchemaCompare)
14+
1. [What database providers does it support](#what-database-providers-does-it-support)
15+
2. [What does EfSchemaCompare check?](#what-does-EfSchemaCompare-check)
16+
3. [List of limitations](#List-of-limitations)
17+
4. [Introduction to how EfSchemaCompare works](#Introduction-to-how-EfSchemaCompare-works)
18+
5. [How to use EfSchemaCompare](#How-to-use-EfSchemaCompare)
1819
5. [Different parameters to the `CompareEfWithDb` method](#different-parameters-to-the-compareefwithdb-method)
19-
5. [Understanding the error messages](#Understanding-the-error-messages)
20-
6. [How to suppress certain error messages](#How-to-suppress-certain-error-messages)
21-
7. [Other configuration options](#Other-configuration-options)
20+
6. [Understanding the error messages](#Understanding-the-error-messages)
21+
7. [How to suppress certain error messages](#How-to-suppress-certain-error-messages)
22+
8. [Other configuration options](#Other-configuration-options)
2223

2324
**NOTE:** I use the term *entity class* for classes mapped to the database by EF Core.
2425

26+
## What database providers does it support
27+
28+
- Version 8 now compares all EF Core database providers that can be [be scaffolded](https://learn.microsoft.com/en-us/ef/core/managing-schemas/scaffolding/). However some database providers may show incorrect match errors, because some database providers don't follow the SqlServer style, e.g. CosmosDB
29+
- Versions below 8 support:
30+
- SqlServer
31+
- Sqlite
32+
- Npgsql.EntityFrameworkCore.PostgreSQL
33+
2534
## What does EfSchemaCompare check?
2635

2736
### Stage 1 - checks on EF Core side
@@ -55,7 +64,8 @@ The EfCore.SchemaCompare library (shortened to EfSchemaCompare in the documentat
5564
- 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.
5665
- 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).
5766
- Cannot compare database tables/columns using InvariantCultureIgnoreCase. That is a EF Core 5+ limitation.
58-
- At the moment this library only supports SQL Server, Sqlite and PostgresSql.
67+
- EfCore.SchemaCompare versions below 8 only support SQL Server, Sqlite and PostgresSql, but version 8 supports all EF Core database providers that can be be scaffolded. However some database providers may show incorrect match errors, because some database providers don't follow the SqlServer style, e.g. CosmosDB
68+
- Version 8 doesn't handle EF Core 8's [Value objects](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#value-objects-using-complex-types).
5969

6070
The following are things I haven't bothered to check.
6171

ReleaseNotes.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
# Release notes
22

3-
## 8.0.0-rc1-0001
3+
## 8.0.0-rc2-0002
44

5-
- First build using NET 8-rc1
5+
- Supports .NET 8-rc.2 - please try this version and report any problems
6+
- NEW FEATURE: Now compares all EF Core database providers, but some database providers may show incorrect match errors
7+
- BREAKING CHANGE: You need to add the Microsoft.EntityFrameworkCore.Design NuGet to your
8+
- Bug Fix: Fix to issue #21
69

710
## 7.0.0
811

912
- Updated to EF Core 7.0
1013

11-
## 6.0.1
14+
## 6.0.2
1215

13-
Fix to issue #21
16+
- Fix to issue #21, but now catches "Not In Database" errors, as seen in issue #25
1417

1518
## 6.0.1
1619

17-
Fix to issue #21
20+
- Fix to issue #21
1821

1922
## 6.0.0
2023

Test/Test.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
<ItemGroup>
1010
<PackageReference Include="EfCore.TestSupport" Version="8.0.0-rc1-0001" />
11-
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.1.23419.6" />
12-
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.1.23419.6" />
11+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.2.23480.1" />
12+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.2.23480.1" />
1313
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
1414
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
1515
<PackageReference Include="xunit" Version="2.5.1" />

0 commit comments

Comments
 (0)