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

Exception with optional navigation properties #29

Open
simon-reynolds opened this issue May 1, 2019 · 5 comments
Open

Exception with optional navigation properties #29

simon-reynolds opened this issue May 1, 2019 · 5 comments
Assignees

Comments

@simon-reynolds
Copy link
Collaborator

Attempting to register optional properties automatically (#24) results in the following error in the Northwind database

System.InvalidOperationException:
The relationship from 'Products.Category' to 'Categories.Products' with foreign key properties {'CategoryId' : FSharpOption<short>} cannot target the primary key {'CategoryId' : short} because it is not compatible.
Configure a principal key or a set of compatible foreign key properties for this relationship.

Optional navigation properties need to be supported, mapping from int option to int and TEntity option to TEntity will need to be added

@simon-reynolds simon-reynolds self-assigned this May 1, 2019
@bricelam
Copy link
Member

bricelam commented May 2, 2019

cc @AndriySvyryd in case he has any pointers

@AndriySvyryd
Copy link

We would need to add explicit support for this in Core to get a nice experience.
The best workaround I can think of is to use a Nullable private field that is wrapped by the optional property. Then configure the relationship to use the field and ignore the property.

@simon-reynolds
Copy link
Collaborator Author

Nullable private fields wouldn't be able to work on an F# record types, similar to C# records, private fields do not exist in them

Given that C# records are now a thing, and reference types in C# can now be annotated in not nullable, is there any support for optional types similar to what is planned for record types in dotnet/efcore#11457?

@simon-reynolds
Copy link
Collaborator Author

Seems like this could be solved by dotnet/efcore#22542

@LiteracyFanatic
Copy link
Contributor

Thought I would post a small working sample since it took me a while to figure out how exactly

The best workaround I can think of is to use a Nullable private field that is wrapped by the optional property. Then configure the relationship to use the field and ignore the property.

translates to code.

[<AllowNullLiteral>]
type Comment() =
    [<DefaultValue>] val mutable private _Id: int
    // Backing field is a regular class which can be null
    [<DefaultValue>] val mutable private _Parent: Comment
    [<DefaultValue>] val mutable private _Text: string
    member this.Id with get() = this._Id and set v = this._Id <- v
    // Property is converted to and from Option
    member this.Parent with get() = Option.ofObj this._Parent and set v = this._Parent <- Option.toObj v
    member this.Text with get() = this._Text and set v = this._Text <- v

type CommentContext =
    inherit DbContext

    [<DefaultValue>] val mutable private _Comments: DbSet<Comment>
    member this.Comments with get() = this._Comments and set v = this._Comments <- v

    override this.OnModelCreating(modelBuilder: ModelBuilder) =

            member this.Configure(builder) =
                // Tell EF Core to ignore the property and use the field directly for the relationship
                builder.Ignore("Parent")
                    |> ignore
                
                builder.HasOne("_Parent")
                    .WithMany()
                    // Set the key you want to appear in the database
                    .HasForeignKey("ParentId")
                    |> ignore

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

No branches or pull requests

4 participants