efcore / EFCore.FSharp

Adds F# design-time support to EF Core
MIT License
228 stars 26 forks source link

Multi-Part Composite Key causes "Find" Exception using tryFindEntity / updateEntity #131

Closed kirse closed 2 years ago

kirse commented 2 years ago

General setup:

// Whatever context config, but create an entity with composite key:
modelBuilder.Entity<CompositeKeyEntity>().HasKey([| "Key1"; "Key2"; "KeyN" |]) |> ignore

Then try:

tryFindEntity<CompositeKeyEntity> db (fun (x : CompositeKeyEntity) -> (x.Key1, x.Key2, x.KeyN) :> obj)

Or this:

tryFindEntity<CompositeKeyEntity> db (fun (x : CompositeKeyEntity) -> 
    let key : obj[] = [| x.Key1; x.Key2; x.KeyN |]
    key)

Which causes this:

System.ArgumentException: Entity type 'CompositeKeyEntity' is defined with a 3-part composite key, but 1 values were passed to the 'Find' method.
at Microsoft.EntityFrameworkCore.Internal.EntityFinder`1.FindTracked(Object[] keyValues, IReadOnlyList`1& keyProperties)
at Microsoft.EntityFrameworkCore.Internal.EntityFinder`1.Find(Object[] keyValues)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Find(Object[] keyValues)

Not hugely impactful since .Find() can be used directly, but treating key as obj instead of obj[] means composite keys can't be used with the helper functions (and they are helpful in many cases).

simon-reynolds commented 2 years ago

This has been fixed in v6.0.6

The only caveat is that a composite key has to be an obj[] or obj list, so you'd need to use the second option above

tryFindEntity<CompositeKeyEntity> db (fun (x : CompositeKeyEntity) -> 
    let key : obj[] = [| x.Key1; x.Key2; x.KeyN |]
    key)
kirse commented 2 years ago

Awesome, thanks, love the project and using it daily!

simon-reynolds commented 2 years ago

Thank you, it's always great to hear when someone is getting some use out of it

kirse commented 2 years ago

On rev-ing to 6.0.6 it appears the DbContextHelpers.fs methods now return everything of type obj instead of 'a, is this intended?

Ex:

let myBlog = tryFindEntity<Blog> db id
// type of myBlog is now obj instead of Blog

I think this breaks a lot of the docs here as well: https://efcore.github.io/EFCore.FSharp//How_Tos/Use_DbContextHelpers.html

@simon-reynolds Any insight, should I create a separate issue?