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

EF Core 5 support #56

Closed
tomiaijo opened this issue Feb 17, 2021 · 18 comments · Fixed by #64
Closed

EF Core 5 support #56

tomiaijo opened this issue Feb 17, 2021 · 18 comments · Fixed by #64

Comments

@tomiaijo
Copy link

tomiaijo commented Feb 17, 2021

Is your feature request related to a problem? Please describe.
Is support for EF Core 5 planned? Seems like some of the interfaces have changed.

Output of running against EF Core 5.0.3 project:

→ dotnet ef migrations add Initial
Build started...
Build succeeded.
System.MissingMethodException: Method not found: 'System.String Microsoft.EntityFrameworkCore.Design.ICSharpHelper.Lambda(System.Collections.Generic.IReadOnlyList`1<System.String>)'.
   at EntityFrameworkCore.FSharp.EFCoreFSharpServices.Microsoft-EntityFrameworkCore-Design-IDesignTimeServices-ConfigureDesignTimeServices(IServiceCollection services)
   at DesignTimeServices.DesignTimeServices.Microsoft.EntityFrameworkCore.Design.IDesignTimeServices.ConfigureDesignTimeServices(IServiceCollection serviceCollection) in /home/tomiaijo/also/eol-pricing-tool/src/Server/DesignTimeServices.fs:line 13
   at Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder.ConfigureDesignTimeServices(Type designTimeServicesType, IServiceCollection services)
   at Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder.ConfigureUserServices(IServiceCollection services)
   at Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder.Build(DbContext context)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Method not found: 'System.String Microsoft.EntityFrameworkCore.Design.ICSharpHelper.Lambda(System.Collections.Generic.IReadOnlyList`1<System.String>)'.

@dsshep
Copy link
Collaborator

dsshep commented Feb 17, 2021

There's a series of API changes from 3.1.x -> 5.x that'll need to be figured out:

// Removed
IAnnotationCodeGenerator.IsHandledByConvention
IAnnotationCodeGenerator.GenerateFluentApi
CoreAnnotationNames.TypeMapping
CoreAnnotationNames.ChangeTrackingStrategy
ChangeDetector.SkipDetectChangesAnnotation
Microsoft.EntityFrameworkCore.Internal.TypeExtensions.GetNamespaces
Type.DisplayName
Multigraph<T>
IEntityType.IsIgnoredByMigrations()
Type.GetNamespaces()

//Changed
IProperty.IsFixedLength() // bool to Nullable<bool>
ICSharpDbContextGenerator.WriteCode // changed signature
INavigation.IsCollection() // changed from method to property

(also I'm getting a stackoverflow problem with paket)

It shouldn't be a huge job. The code structure roughly follows the C# implementation so it should be a case of side-by-siding and figuring out how the API has changed.

As there has never been a nuget release it would seem to make sense to shift to the latest packages. I'll have a look at it sometime this week.

@simon-reynolds
Copy link
Collaborator

Hi, support is planned, and slowly in progress
I've created a branch https://github.com/efcore/EFCore.FSharp/tree/net5.0 that targets the latest version of EF Core (5.0.3)

So far it's just getting everything targeting NET 5.0, I've handled the Type.GetNamespaces() API change but everything else is still in progress.
@DurdSoft, thanks for the list above, I'm happy to work through them with you and hopefully we can actually get a release out

@dsshep
Copy link
Collaborator

dsshep commented Feb 18, 2021

I think the 2 main pain points will be:

  • Annotations - some have been removed, others deprecated. I'm not sure if there's a reason why we didn't or don't just use IAnnotationCodeGenerator and the DB specific implementations in EF Core? This would put FSharpMigrationsGenerator and FSharpDbContextGenerator on a diet.
  • Multigraph<T> has been made internal. This seems to be important in making sure the snapshots are generated in a logical order. I'm not sure what the best way forward here would be.

@simon-reynolds
Copy link
Collaborator

Because when I first started working on this back in the 2.x days, IAnnotationCodeGenerator didn't exist 😄
I'm currently working through FSharpDbContextGenerator at the moment and yeah, it's definitely going to be losing a lot of complexity

Trying to figure out the best way to handle Multigraph<T>, shall have to see what we can come up with
Maybe something that @bricelam may have some ideas on if he has a chance to take a look?

@dsshep
Copy link
Collaborator

dsshep commented Feb 18, 2021

That makes sense! I've built off your branch some more of the required code changes here. 2 of the unit tests are failing and I've side stepped the Multigraph<T> issue.

@simon-reynolds
Copy link
Collaborator

Perfect! Can you create a PR for that please?
Getting as far as unit tests running in order to fail means you're ahead of me 😀

@dsshep
Copy link
Collaborator

dsshep commented Feb 20, 2021

I've updated my branch to fix the tests. Most the work is done to migrate to AnnotationCodeGenerator.

There's a failing test still - the one related to snapshot enum generation that was commented out. I think there's a genuine issue here. The C# generation up to the point where c.ConvertToProvider.Invoke(defaultValue) is called looks like:

// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations.Design;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace MyNamespace
{
    [DbContext(typeof(CSharpMigrationsGeneratorTest.MyContext))]
    partial class MySnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618

            modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest+WithAnnotations", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("default_int_mapping");

                    b.Property<int>("EnumDiscriminator")
                        .HasColumnType("default_int_mapping");

                    b.HasKey("Id");

                    b.ToTable("WithAnnotations");

                    b.HasDiscriminator<int>("EnumDiscriminator")

Whereas the F# version:

namespace MyNamespace

open System
open EntityFrameworkCore.FSharp.Test.Migrations.Design
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Infrastructure
open Microsoft.EntityFrameworkCore.Metadata
open Microsoft.EntityFrameworkCore.Migrations
open Microsoft.EntityFrameworkCore.Storage.ValueConversion

[<DbContext(typeof<MyContext>)>]
type MySnapshot() =
    inherit ModelSnapshot()

    override this.BuildModel(modelBuilder: ModelBuilder) =

        modelBuilder.Entity("EntityFrameworkCore.FSharp.Test.Migrations.Design.Derived", (fun b ->

            b.HasBaseType("EntityFrameworkCore.FSharp.Test.Migrations.Design.WithAnnotations")
            b.HasDiscriminator()

This was probably broken in the code in 3.1 as well.

@simon-reynolds
Copy link
Collaborator

That's some really great work! Can you create a PR again for these changes please?

@bricelam, whenever you get a chance to see this, can you add @DurdSoft as a collaborator to this repo?

@dsshep
Copy link
Collaborator

dsshep commented Feb 20, 2021

The issue was related to the missing Multigraph and some misconfiguration in the test setup. I've added a slightly naive implementation of Multigraph (until we can decide what we want to do with it) which is enough to get it over the line - I'll put in a PR 👍

@dsshep
Copy link
Collaborator

dsshep commented Feb 20, 2021

I've put in another PR for a silly mistake I'd made, sorry!

There are still a few outstanding issues in scaffolding:

  • Build is failing - not too sure what's changed on this ?

  • HasIndex is failing now where it worked on 3.1. In this screenshot, it should be using the Expression<_>, string overload but doesn't seem at all happy with it. I wonder if something changed in net 5.0 (or more likely, it's something way more obvious).

image

If either argument is removed it is happy again.

  • ToTable is missing for modelBuilder entities on DbContext.

@simon-reynolds
Copy link
Collaborator

I'm working my way through the DbContextGenerator so I'll take care of ToTable

Looks like the compiler currently thinks the expression is supposed to a tuple of obj * string so you should be able to get HasIndex working if you put parentheses around the expression
.HasIndex((fun e -> e.EntityId :> obj), "exntity_id_idx")

@dsshep
Copy link
Collaborator

dsshep commented Feb 21, 2021

D'oh, of course. I'm going to look into migrating more of the unit tests so we can get it 1 to 1 with C#. I'm surprised none of the existing ones have caught that missing ToTable(...) call - and there'll probably be similar bits like that in their as well.

@simon-reynolds
Copy link
Collaborator

Cool, I'm going to look at tidying up the implementations in Snapshot, DbContext and Migration generators so bring them more in line with the changes in EFCore for net5.0

@simon-reynolds
Copy link
Collaborator

Hi @DurdSoft
The enum test now passes, if we can add more tests to bring to parity with C# that would be great

@bricelam
Copy link
Member

bricelam commented Feb 26, 2021

@simon-reynolds I've added @DurdSoft and made you an admin.

Copying/porting Multigraph into this project is the right thing to do.

@tomiaijo
Copy link
Author

I tested the net5.0 branch. Migrations seems to created ok, but have a few minor issues.

Two opens missing:

open Microsoft.EntityFrameworkCore.Migrations.Operations.Builders
open Microsoft.EntityFrameworkCore.Migrations.Operations

Some syntax errors:

  • Two commas after name in CreateTable
  • Fields have comma missing between nullable and type, and an extra comma after type
  • Fields have extra comma at the end

image

table.ForeignKey, migrationBuilder.DropTable and migrationBuilder.CreateIndex have also an extra comma at the end
image

table.Foreignkeyis missing newline and comma after column:
image

With these changes I was able to migrate our database, great work!

@simon-reynolds
Copy link
Collaborator

Hi @tomiaijo
Thank you so much for the feedback and the kind words

I'll see what I can do about these issues and hopefully we'll then be in a good enough state to be able to release a NuGet package

@simon-reynolds
Copy link
Collaborator

Hi @tomiaijo,
Can you try this with the latest commits on the net5.0 branch?
I just pushed a change to correct an issue affecting CreateTable operations

I couldn't see the issues you encountered though. I was able to create an example using basic MVC authentication at https://github.com/simon-reynolds/EFCore.FSharp.MvcAuth
Can you try with the latest versions and let me know if you're still having the same problems?
I've included the latest version of the nuget package at https://github.com/simon-reynolds/EFCore.FSharp.MvcAuth/tree/main/packages

@simon-reynolds simon-reynolds mentioned this issue Mar 21, 2021
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

4 participants