我试图将带有F#的Entity Framework Core与内存数据库一起用于一个非常简单的用例:
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
但它不起作用并抛出以下异常:
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
如何使其工作,OnConfiguring覆盖存在,所以我不是我在这里缺少的。
猜测,我想知道这条线是否是罪魁祸首:
if optionsBuilder.IsConfigured <> false then
optionsBuilder.UseInMemoryDatabase("database_name") |> ignore
每个OnConfiguring
实例只能由EFCore调用DbContext
,所以你可能不需要在这里检查IsConfigured
。尝试删除if
分支,然后再试一次?
有一些问题:
OnConfiguring
方法没有正确实现,需要检查是否已经配置(而不是像我最初那样)解决方案:
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