question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to use an Id well in Classes, and save mutable values to LiteDB

See original GitHub issue

Hi @Zaid-Ajaj, I would like to use an autoincremental Id also in Classes. In the documentation it is very well explained that when it comes to records we have to classify it as [<CLIMutable>] and put Id = 0 so that the Identifier autoincrements itself. But that is not so established with the classes. I ask if there is a plan to do it also in classes?

In the meantime testing witdh this example class

type Article( Id: ObjectId, Name: string) as self =
    let mutable mutableValue = 0 
    do
        mutableValue <- 10
        printfn "Initialized object"
    // private mutable value
    member val Id = Id //Read Only 
    member val Name = Name with get, set
    // public wrapper for mutable value
    member this.SetMutableValue x = 
        mutableValue <- x 

The Id type set to ObjectId type and get one before inserting a new Article like this: let myArticle = new Article(ObjectId.NewObjectId(), "title")

I’m not sure that’s the best way, since: let result = articles.FindById(myArticle.Id) shows the following error:

error FS0193: Type constraint mismatch. The type 'ObjectId' is not compatible with type 'BsonValue'.

I accept it’s not the right type and I try that way: let result = articles.findOne <@ fun a -> a.Id = myArticle.Id @>, and everything works until I change the = for another operator <= to: let result = articles.findOne <@ fun a -> a.Id <= myArticle.Id @> and get:

error FS0001: The type 'ObjectId' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface

The only issue here is that I don’t know which is the correct way to use Id in a Class, if I want the DB to assign them automatically.

At the same time and with the class I’ve expounded before. Only the constructor parameters are stored in the DB, the let mutable mutableValue is not stored. Is there any way they persist in the database, which I’ve overlooked? If this is the behavior designed, we adapt without problems. But I think it will be interesting for the product that these values are saved in the DB by default, and if you don’t want to apply them [<BsonIgnore>].

Thank you for everything. And it’s really great work you’re doing with LiteDB.FSharp.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
srlopezcommented, May 8, 2019

Thanks @Zaid-Ajaj, @humhei It was misunderstood on my part. In a class with Id as int without get and set, and that way you couldn’t assign Id from LiteDB. Then I tried to use ObjectID. By fixing that, as @humhei reminded me, you can use Id as int, and LiteDB assigns the number correlatively.

You are right when you say that ObjetcID adds coupling, but if it’s used as a GUI. But as it is currently calculated as sequential, which will be the same as an int. https://github.com/mbdavid/LiteDB/wiki/Data-Structure

Unlike the Guid data type, ObjectIds are sequential, so it’s a better solution for indexing. ObjectIds use hexadecimal numbers represented as strings.

So the @humhei’s fix

Only the = operator is supported (but now does with the other operators too thanks to @humhei)

has come in handy for all of us and is perfectly correct. Thanks guys.

0reactions
Zaid-Ajajcommented, May 8, 2019

As explained in #29 there is a reason that comparison operators don’t work with identities: it doesn’t make sense. The Id property to identify a single record of data, not a range of records. Which is also why ObjectID doesn’t implement IComparable: it doesn’t need to.

As for using classes in LiteDB.FSharp, I don’t know why you would do that because again this introduces tight coupling between the persistence layer (modeling the record types) with your business layer (modeling behavior in your classes). Trying to hide the lambda expressions to make the model “readable” by domain expects isn’t really a solution. Using classes is arguable less readable compared to just plain old functions:

type Computer = { Id: int; Manufacture: string }

module Computers = 

  let private computerDocuments = db.GetCollection<Computer>("computers")
  let getAll() = computerDocuments.FindAll()
  let findByManufacture (input: string) = computerDocuments.findMany (fun c -> c.Manufacture.Contains input)

I guess this answers your comment about domain modeling? (sorry I can’t find it anymore)

If you can get this library to work with classes, then that is fine but it is really out of scope of this library to support classes: not idiomatic F#. The documentation clarifies this in the readme file:

LiteDB.FSharp is made mainly to work with records as representations of the persisted documents

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to handle class inheritance in LiteDB with custom IDs
I would like to persist a class which implements an interface and can have various subclasses. I am just trying to understand how...
Read more >
Object Mapping - LiteDB :: A .NET embedded NoSQL ...
The LiteDB mapper converts POCO classes documents. When you get a ILiteCollection<T> instance from LiteDatabase.GetCollection<T> , T will be your document ...
Read more >
UltraLiteDB/README.md at master
This is a great library to use for any project that needs to store lots of mutable data in a convenient and accessible...
Read more >
Data Structure - LiteDB :: A .NET embedded NoSQL ...
LiteDB stores data as documents, which are JSON-like objects containing key-value pairs. Documents are a schema-less data structure. Each document stores both ...
Read more >
How can i insert complex entities to db? · Issue #460 ...
Because of that i start to use LiteDB in my project. I implement my simple entities first insert, update etc working fine.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found