Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a more complete guide to porting from EF6 #1180

Closed
ajcvickers opened this issue Dec 15, 2018 · 6 comments · Fixed by #3509
Closed

Provide a more complete guide to porting from EF6 #1180

ajcvickers opened this issue Dec 15, 2018 · 6 comments · Fixed by #3509
Assignees
Milestone

Comments

@ajcvickers
Copy link
Contributor

Moving from EF6 to EF Core must be considered a porting exercise, rather than a version upgrade, since they are different code bases with different functionality. We should provide more details on this porting and common things that people hit. See dotnet/efcore#14130


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@divega divega added the help wanted This issue involves technologies where we are not experts. Expert help would be appreciated. label Feb 21, 2019
@m17kea
Copy link

m17kea commented Feb 26, 2019

@ajcvickers, @maumar, @smitpatel, guys as you've been so helpful with my migration to ef core I'd be happy to contribute here and write some documentation. I'll write up all of the migration steps I have been through, as soon as I'm finished with the migration itself.

@MrJinx
Copy link

MrJinx commented Jul 12, 2019

Just came across this post while looking to implement Alternate Keys in an existing EF 6 application. I haven't been able to find much information on moving from EF 6 to EF Core though. I'd like to be on the latest version of EF, however, I'm concerned with how porting to EF Core will impact our existing application, model and data. Any helpful insight would be greatly appreciated by anyone who has ported an existing application. Thanks!

@ErikEJ
Copy link
Contributor

ErikEJ commented Jul 12, 2019

@MrJinx Useful info in the video: https://channel9.msdn.com/Shows/On-NET/Migrating-from-Entity-Framework-6-to-Core

@MrJinx
Copy link

MrJinx commented Jul 13, 2019

Thanks Erik! I'll definitely check it out.

@ajcvickers ajcvickers added area-ef6 area-getting-started type-enhancement and removed area-ef6 help wanted This issue involves technologies where we are not experts. Expert help would be appreciated. labels Aug 29, 2019
@ajcvickers ajcvickers added this to the Backlog milestone Aug 29, 2019
@ajcvickers ajcvickers modified the milestones: Backlog, 3.1.0 Sep 6, 2019
@divega
Copy link
Contributor

divega commented Sep 17, 2019

These are some raw materials to help us add to the documentation:

Besides the video referenced by @ErikEJ above (https://channel9.msdn.com/Shows/On-NET/Migrating-from-Entity-Framework-6-to-Core) I did another video about migrating when you have an EDMX file. I will find out where it is.

Here is some notes from recent migration exercises I was involved in:

Phase 1: Changing references and getting the code to compile again

  1. Remove unnecessary dependencies/packages (including EntityFramework) from DAL project

  2. Upgrade DAL to PackageReference (but stay on .NET Framework for now)

  3. Install Microsoft.EntityFramework.SqlServer 2.2

  4. Replace using clauses on all files from System.Data.Entity to Microsoft.EntityFrameworkCore. This helps all EF Core types used the source, but specially extension methods to continue working

  5. Change DbContext constructor to set the a new _connectionString field and override OnConfiguring to call UseSqlServer(_connectionString)

  6. Rename DbModelBuilder to ModelBuilder: We changed the name of this class unnecessarily when we created EF Core, but it is typically only used once per DbContext, on OnModelCreating, so it is not a big deal.

  7. Rename DbEntityEntry<T> to EntityEntry<T>: This was another unnecessary change when we created EF Core. In many cases it is used in a variable declaration, in which case the simplest fix is to change to use var.

  8. Commented out usage of Database.Log: This is a minor functionality removal, but one that can be replaced with Microsoft.Extensions.Logging APIs.

  9. Change WithRequired/WithOptional to WithOne+IsRequired(bool) and WillCascadeDelete(bool) to OnDelete(DeleteBehavior): These APIs were intentionally designed differently on EF Core. Since there around two hundred calls and it wasn’t always simple search and replace, the solution adopted was to re-implement the missing methods as extension methods in application code.

  10. Data validation removal: This is an EF6 feature that is intentionally not implemented in EF Core. Commented ValidateEntity and code related to validation exceptions on SaveChanges. They had loads of code taking advantage of this feature with the goal of throwing user-friendly errors instead of database server errors. We explained the removal of the feature and how they can implement data validation themselves. For example overriding SaveChanges and writing your own code that iterates over entries, etc.

  11. Add ToObservableCollection() call after all usages of .Local: We had to do this pretty much everywhere there was a call to .Local (tens of times). It was only bit annoying to have to make the change and they were satisfied to learn that .Local is now much more efficient in EF Core, but that you need the extra call when you plan to use data binding.

  12. Add key-less entities on OnModelCreating for types mapped ad-hoc through Database.SqlQuery

  • If we initially use 2.2, use the query types API, on 3.0 so we should use .HasNoKey() calls
  • We had cases of SqlQuery was invoked to return a stream of scalars, which EF Core doesn’t support yet. We implemented a workaround with a FromSql query type that contains a single property of that scalar type and then project the scalar type in the query.

Phase 2: Getting things to run

  1. The original project removed the pluralization convention used by default with EF6, meaning that tables names match entity types in singular form, and not the names of the DbSets properties, which is the default in EF Core. We achieved the same result with this code at the end of OnModelCreating
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) 
{ 
modelBuilder.Entity(entityType.Name).ToTable(entityType.ClrType.Name); 
}
  1. There was a large number of entities with composite keys specified using KeyAttribute and ColumnAttribute. EF Core intentionally does not support this pattern because it can lead to arbitrary key member ordering. Converting to HasKey calls was time consuming, especailly because some of the entities had keys with up to 9 member properties. We wish we had some way to express composite keys with attributes again.

Phase 3: Target .NET Standard 2.0 or .NET Core 3.0

  • Had to change code to use query types instead of key-less entity types

  • You cannot call modelBuilder.Entity(entityType.Name).ToTable(entityType.ClrType.Name) without checking first if is an actual entity type

@divega divega assigned bricelam and ajcvickers and unassigned divega Sep 18, 2019
@AndriySvyryd
Copy link
Member

AndriySvyryd commented Dec 10, 2019

Related: #1989, #1971, #684

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants