Some older projects .NET Framework project will have EDMX instead of modern DbContext first introduced in Entity Framework 4.1, which first introduced DbContext and Code-First approach back in 2012, replacing the ObjectContext that EDMX used for Database-First approach.
In this rule, we’ll use ObjectContext and Entities interchangeably. ObjectContext is the base class that is used by the generated class, which will generally end with Entities (e.g. DataEntities).
The rule is focusing on .NET 8+ as the support for .NET Framework projects and Nuget was added back, which makes a staged migration a lot more feasible. Most, if not all, are still applicable for .NET 7 as well.
There are a few strategies regarding the migration from a full rewrite with to a more in-place migration. Depending on the scale and complexity of the project. This rule will describe an approach that balances the code we need to rewrite and modernisation.
The focus is to minimise the amount of time no deployments are made due to migration.
The strategy in this rules will include:
ObjectContext/Entities class with a custom IDbContext interface (e.g. ITenantDbContext)DbContext.OnConfiguringObjectSet<T> with DbSet<T>.AsEnumerable(), use raw SQL or change how the query worksSystem.Data.Entity namespace in all files using EF Core 3.1 (otherwise, you'll get odd Linq exceptions)Microsoft.EntityFrameworkCore namespace.AddDbContext() or .AddDbContextPool()Steps 6 and 7 are required when upgrading from .NET Framework to .NET 8 and the solution is too complex to do the migration in one go. For simple projects, if EDMX is the only major blocking issue, they should go straight to .NET 8 and EF Core 8.
NOTE: With some smart abstraction strategies, it is possible to do steps 3 - 5 while still having a working application. It is only recommended for experienced developers in architecture and how EF operates to avoid bugs related to running 2 EF tracking systems. This will impact EF internal caching and saving changes.
In this rule, we'll only cover abstracting access to ObjectContext with a custom IDbContext and how to scaffold the DB. The rest of the steps require in-depth code review and may differ greatly between projects.
Before starting, it’s important to note that ObjectContext and EDMX are no longer supported and we need to do a full rewrite of the data layer. You can wrap ObjectContext with an interface that looks like modern DbContext, as most commonly used methods are identical.
The wrapper below not only allows us to use ObjectContext in a cleaner way (see Rules to Better Clean Architecture) but also allows us to better manage the differences between ObjectContext and DbContext without needing to refactor the business logic.
using System.Data.Entity.Core.Objects;public interface ITenantDbContext{ObjectSet<Client> Clients { get; }int SaveChanges();Task<int> SaveChangesAsync(CancellationToken ct = default);}/// <summary>/// Implement DbContext as internal, so that external libraries cannot access it directly./// Expose functionality via interfaces instead./// </summary>internal class TenantDbContext : ITenantDbContext{private readonly DataEntities _entities;public TenantDbContext(DataEntities entities){_entities = entities;}public ObjectSet<Client> Clients => _entities.Clients;public int SaveChanges() => _entities.SaveChanges();public Task<int> SaveChangesAsync(CancellationToken ct = default) => _entities.SaveChangesAsync(ct);}
✅ Figure: Abstracting ObjectEntities behind an interface and using an interface to reduce the amount of issues while migrating.
NOTE: The changes made in this section are still compatible with .NET Framework, allowing us to deliver value to the clients while the above changes are made.
Now that we abstracted access to the data, it's time to scaffold the DB. The easiest way to do this is by using EF Core Power Tools.
Figure: Select reverse engineer tool
Figure: Data Connection
Figure: Database Objects
Figure: Settings for project
Persistence folderFigure: Settings for project
DbContext class will be auto-generated by EF Core Power ToolsFigure: Settings for project
EF Core 3.1 EDMX - Walk-through: Using an Entity Framework 6 EDMX file with .NET Core | ErikEJ's blog
While the above blog is supposedly working in EF Core 3.1, there is no information on whether that is true for .NET 8. It would still require a lot of migrations.
Limitations: