Closed srlopez closed 5 years ago
You should set Val id with get and set; https://github.com/mbdavid/LiteDB/blob/0864d8f888af427571487b84652567c1fd78d97f/LiteDB.Tests/Database/AutoId_Tests.cs#L12
I don't know how does it get worked With a readonly property
type Article(Name: string) =
// private mutable value
member val Id = new ObjectId() with get,set
member val Name = Name with get, set
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?
By default, field is not expected to serialized by converter(While property is)
The purpose of Bsonfield in official Reposity is only to specfic the Name in database and make private internal protectd property serialiable
Both Bsonfield and Bsonignore are desired to apply to properties
https://github.com/mbdavid/LiteDB/search?q=BsonField&unscoped_q=BsonField
Correct me if i am wrong @Zaid-Ajaj
Thanks @humhei, mutable member doesn't need to be in constructor if they are initialized. I'm learning.
member val mutableMember = 0 with get, set //<- Initialized
member val Name = Name with get, set //<- set on constructor
They are both saved to DB. Thanks
But:
I still don't know which is the correct way to use Id in a Class, if I want the DB to assign them automatically.
And if I continue using 'ObjectId'
as the type of Id
, let result = articles.findOne <@ fun a -> a.Id <= myArticle.Id @>
the error is The type 'ObjectId' does not support the 'comparison' constraint.
Take care about <=
, the =
is working.
This is because that ObjectID doesn't implement IComparable interface
I am using int
instead of ObjectId
If you want use ObjectId anyWay
you should implement IComparable yourselt
For example
type MyObjectId() =
inherit ObjectId()
interface IComparable with
member x.CompareTo y =
----------do your compare here----------------
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
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.
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 torecords
we have to classify it as[<CLIMutable>]
and putId = 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
The
Id
type set toObjectId
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.