Calling EF Core HasIndex from F#

ef-code-first entity-framework-core f#

Question

I'm trying to rewrite a C# EF Core example (similar to the one in the docs) into F#. I have a problem with HasIndex. In C#, the call is HasIndex(b => b.Isbn), to create an index on the Isbn column:

public class SampleContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Book>().HasIndex(b => b.Isbn);
    }
}

Doing the same in F#, HasIndex(fun b -> b.Isbn), doesn't compile:

type public SampleContext() =
    inherit DbContext()

    [<DefaultValue>]
    val mutable books: DbSet<Book>

    member x.Books
        with get() = x.books
        and set v = x.books <- v

    override __.OnModelCreating(modelBuilder) =
        modelBuilder.Entity<Book>().HasIndex(fun b -> b.Isbn) // doesn't compile
        |> ignore

Do I need to use some quotation magic to make this work?

(You can of course use a string, HasIndex("Isbn"), but I'd prefer not to throw compile time checks out the window.)

1
1
3/31/2018 3:11:23 PM

Accepted Answer

According to the accepted answer in https://social.msdn.microsoft.com/Forums/vstudio/en-US/a0757965-4d13-4f88-910f-9ab5fd96277d/how-to-convert-c-linq-expression-in-f?forum=fsharpgeneral:

"F# 3.0 or later should apply a type-directed conversion when you pass a lambda where an Expression is expected."

It seems that F# 3.0 and later will convert the lambda as long as you enclose it with parenthesis and cast the return value to the specific type that the C# method is expecting (in this case "Sytem.Object")

So:

modelBuilder.Entity<Book>().HasIndex( (fun b -> b.Isbn :> System.Object ) )

Compiles successfully in .net core 2.0

2
4/6/2018 1:16:37 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow