Reputation: 8997
I am trying to use Entity Framework Core with F# with the in memory database for a very simple use case:
open System
open Microsoft.EntityFrameworkCore
type Position = {
X: double
Y: double
}
type Airport = {
Id: Guid
Name: string
Position: Position
}
type MyContext =
inherit DbContext
new() = { inherit DbContext() }
new(options: DbContextOptions<MyContext>) = { inherit DbContext(options) }
override __.OnConfiguring optionsBuilder =
if optionsBuilder.IsConfigured <> false then
optionsBuilder.UseInMemoryDatabase("database_name") |> ignore
[<DefaultValue>]
val mutable airports: DbSet<Airport>
member x.Airports
with get() = x.airports
and set value = x.airports <- value
module AirportRepository =
let getAirport id =
use context = new MyContext()
query {
for airport in context.Airports do
where (airport.Id = id)
select airport
exactlyOne
} |> (fun x -> if box x = null then None else Some x)
let addAirport (entity: Airport) =
use context = new MyContext()
context.Airports.Add(entity) |> ignore
context.SaveChanges true |> ignore
[<EntryPoint>]
let main argv =
let airport = {
Id = Guid.NewGuid()
Name = "Michelle"
Position = {
X = 42.0
Y = 42.0
}
}
AirportRepository.addAirport airport
0
but it does not work and throw the following exception:
Unhandled Exception: System.InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application se
rvice provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.EntryWithoutDetectChanges[TEntity](TEntity entity)
at Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState)
at Program.AirportRepository.addAirport(Airport entity) in C:\Users\eperret\RiderProjects\FSharpCore\FSharpCore\Program.fs:line 43
at Program.main(String[] argv) in C:\Users\eperret\RiderProjects\FSharpCore\FSharpCore\Program.fs:line 56
How can I make it work, the OnConfiguring override is present so I am not really what I am missing here.
Upvotes: 1
Views: 901
Reputation: 8997
There was a few issues:
OnConfiguring
method was not properly implemented and needed to check if was not already configured (and not the opposite like what I initially did)The solution:
open System
open Microsoft.EntityFrameworkCore
[<CLIMutable>]
type Airport = {
Id: Guid
Name: string
X: double
Y: double
}
type MyContext =
inherit DbContext
new() = { inherit DbContext() }
new(options: DbContextOptions<MyContext>) = { inherit DbContext(options) }
override __.OnConfiguring optionsBuilder =
if optionsBuilder.IsConfigured <> true then
optionsBuilder.UseInMemoryDatabase("database_name") |> ignore
[<DefaultValue>]
val mutable airports: DbSet<Airport>
member x.Airports
with get() = x.airports
and set value = x.airports <- value
module AirportRepository =
let getAirport id =
use context = new MyContext()
query {
for airport in context.Airports do
where (airport.Id = id)
select airport
exactlyOne
} |> (fun x -> if box x = null then None else Some x)
let addAirport (entity: Airport) =
use context = new MyContext()
context.Airports.Add(entity) |> ignore
context.SaveChanges true |> ignore
[<EntryPoint>]
let main argv =
let myGuid = Guid.NewGuid()
let airport = {
Id = myGuid
Name = "Michelle"
X = 42.0
Y = 42.0
}
AirportRepository.addAirport airport
let thisAirport = AirportRepository.getAirport myGuid
assert (thisAirport = Some airport)
0
Upvotes: 0
Reputation: 61589
At a guess, I'm wondering if this line is the culprit:
if optionsBuilder.IsConfigured <> false then
optionsBuilder.UseInMemoryDatabase("database_name") |> ignore
The OnConfiguring
should only be called by EFCore once per DbContext
instance, so you may not need the check for IsConfigured
here. Try removing that if
branch and try again?
Upvotes: 3