EFCore.FSharp 10.0.0

Edit this page

Querying option types

Configuring

EF Core by default does not know anything about the way of F# deals with nullable values which is the Option type.

This project has a way to enable query for columns defined as an option, first you need to call .UseFSharpTypes() on the context configuration builder

open EntityFrameworkCore.FSharp.Extensions

[<CLIMutable>]
type Blog = {
    [<Key>]
    Id : Guid
    Title : string
    Content : string option
}

type MyContext () =
    inherit DbContext()

    [<DefaultValue>]
    val mutable private _blogs : DbSet<Blog>
    member this.Blogs with get() = this._blogs and set v = this._blogs <- v

    override _.OnModelCreating builder =
        builder.RegisterOptionTypes() // enables option values for all entities

    override _.OnConfiguring(options: DbContextOptionsBuilder) : unit =
           options.UseSqlite("Data Source=dbName.db")
                  .UseFSharpTypes()
           |> ignore

Note that the .UseFSharpTypes() will exist independent of the database, the UseSqlite is just for the example. If you are using an SQL server with UseSqlServer or UsePostgres for Postgres, or any other database it will exist.

Querying

With that, you will be able to query your entity by an optional column.

Querying entities with Some content

let queryWhereSome (ctx: MyContext) =

    // Querying entities with `Some` content
    let blogs =
        query {
            for blog in ctx.Blogs do
            where blog.Content.IsSome
            select blog
        }

    // or using Linq extensions
    let blog =
        ctx.Blogs.Where(fun x -> x.Content.IsSome)

    ()

Querying entities with None content

let queryWhereNone (ctx: MyContext) =

    let blogs =
        query {
            for blog in ctx.Blogs do
            where blog.Content.IsNone
            select blog
        }

    // or using Linq extensions
    let blog =
        ctx.Blogs.Where(fun x -> x.Content.IsNone)

    ()

Querying optional values by value

let queryWhereValue (ctx: MyContext) =

    let blogs =
        query {
            for blog in ctx.Blogs do
            where (blog.Content.Value = "Some text")
            select blog
        }

    // or using Linq extensions
    let blog =
        ctx.Blogs.Where(fun x -> x.Content.Value = "Some text")

    ()
Multiple items
type CLIMutableAttribute = inherit Attribute new: unit -> CLIMutableAttribute

--------------------
new: unit -> CLIMutableAttribute
type Blog = { Id: Guid Title: string Content: string option }
Multiple items
type KeyAttribute = inherit Attribute new: unit -> unit
<summary>Denotes one or more properties that uniquely identify an entity.</summary>

--------------------
KeyAttribute() : KeyAttribute
Blog.Id: Guid
Multiple items
[<Struct>] type Guid = new: b: byte array -> unit + 6 overloads member CompareTo: value: Guid -> int + 1 overload member Equals: g: Guid -> bool + 1 overload member GetHashCode: unit -> int member ToByteArray: unit -> byte array + 1 overload member ToString: unit -> string + 2 overloads member TryFormat: utf8Destination: Span<byte> * bytesWritten: byref<int> * ?format: ReadOnlySpan<char> -> bool + 1 overload member TryWriteBytes: destination: Span<byte> -> bool + 1 overload static member (<) : left: Guid * right: Guid -> bool static member (<=) : left: Guid * right: Guid -> bool ...
<summary>Represents a globally unique identifier (GUID).</summary>

--------------------
Guid ()
Guid(b: byte array) : Guid
Guid(b: ReadOnlySpan<byte>) : Guid
Guid(g: string) : Guid
Guid(b: ReadOnlySpan<byte>, bigEndian: bool) : Guid
Guid(a: int, b: int16, c: int16, d: byte array) : Guid
Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : Guid
Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : Guid
Blog.Title: string
Multiple items
val string: value: 'T -> string

--------------------
type string = String
Blog.Content: string option
type 'T option = Option<'T>
Multiple items
type MyContext = new: unit -> MyContext override OnConfiguring: options: 'a -> unit override OnModelCreating: builder: 'a -> 'b member Blogs: IQueryable<Blog>

--------------------
new: unit -> MyContext
Multiple items
type DefaultValueAttribute = inherit Attribute new: unit -> DefaultValueAttribute + 1 overload member Check: bool

--------------------
new: unit -> DefaultValueAttribute
new: check: bool -> DefaultValueAttribute
MyContext._blogs: obj
val set: elements: seq<'T> -> Set<'T> (requires comparison)
type unit = Unit
val ignore: value: 'T -> unit
val queryWhereSome: ctx: MyContext -> unit
val ctx: MyContext
val blogs: IQueryable<Blog>
val query: Linq.QueryBuilder
val blog: Blog
property MyContext.Blogs: IQueryable<Blog> with get, set
custom operation: where (bool) Calls Linq.QueryBuilder.Where
property Option.IsSome: bool with get
custom operation: select ('Result) Calls Linq.QueryBuilder.Select
val blog: IQueryable<Blog>
(extension) Collections.Generic.IEnumerable.Where<'TSource>(predicate: Func<'TSource,bool>) : Collections.Generic.IEnumerable<'TSource>
(extension) Collections.Generic.IEnumerable.Where<'TSource>(predicate: Func<'TSource,int,bool>) : Collections.Generic.IEnumerable<'TSource>
(extension) IQueryable.Where<'TSource>(predicate: Expressions.Expression<Func<'TSource,bool>>) : IQueryable<'TSource>
(extension) IQueryable.Where<'TSource>(predicate: Expressions.Expression<Func<'TSource,int,bool>>) : IQueryable<'TSource>
val x: Blog
val queryWhereNone: ctx: MyContext -> unit
property Option.IsNone: bool with get
val queryWhereValue: ctx: MyContext -> unit
property Option.Value: string with get