Zaid-Ajaj / LiteDB.FSharp

Advanced F# Support for LiteDB, an embedded NoSql database for .NET with type-safe query expression through F# quotations
MIT License
180 stars 22 forks source link

Opqaue types do not work correctly #52

Closed ericnething closed 3 years ago

ericnething commented 4 years ago

I am using opaque types to wrap ints for the different types of Ids (so as not to confuse them), which LiteDB happily accepts as the Id (_id) field of a record. However, I get an error as soon as I try to include the same type in a Map, or when I try to look up a value by Id.

Given these types,

type GameId = GameId of int
type UserId = UserId of int

type Access =
    | Member
    | Moderator
    | Admin

type User = {
    Id : UserId
    Name : string
    Games : Map<GameId, Access>
}

I can successfully insert a record like this:

let game = {
    Id = GameId 0
    Title = newGame.Title
    Members = Map.empty
    DateCreated = System.DateTime.Now
    GameType = newGame.GameType
}
games.Insert game |> ignore

And I can get the record back with FindAll (), but I cannot get the record by Id. I only get back null.

When I try to insert this record:

let game = {
    Id = GameId 0
    Title = newGame.Title
    Members = Map.ofList [(UserId 1, Admin); (UserId 2, Member)]
    DateCreated = System.DateTime.Now
    GameType = newGame.GameType
}
games.Insert game |> ignore

I get this error:

System.ArgumentException: Field '{"UserId":1}' has an invalid name.

Is there a way to configure LiteDB to work correctly with these opaque types?

The NewtonSoft Json library correctly serializes all of these types (the Id itself and the Id when used as a key in a Map) to look like this:

[
  {
    "Id": {
      "GameId": 1
    },
    "Title": "Wonderland",
    "Members": {
      "UserId 1": "Admin",
      "UserId 2": "Member"
    },
    "DateCreated": "2020-05-27T22:58:13.83011-07:00",
    "GameType": "Alien"
  }
]

I suspect that the Json serializer being used internally by LiteDB is the problem.

Zaid-Ajaj commented 3 years ago

Hi @ericnething this took a while but now using single case union as an ID should work as of v2.16