开发者

Using NoRM to access MongoDB from F#

Testing out NoRM https://github.com/atheken/NoRM from F# and trying to find a nice way to use it. Here is the basic C#:

class products
{
    public ObjectId _id { get; set; }
    public string name { get; set; }
}

using (var c = Mongo.Create("mongodb://127.0.0.1:27017/test"))
{
    var col = c.GetCollection<products>();
    var res = col.Find();
    Console.WriteLine(res.Count().ToString());
}

This works OK but here is how I access it from F#:

type products() = 
    inherit System.Object()

    let mutable id = new ObjectId()
    let mutable _name = ""

    member x._id with get() = id and set(v) = id <- v
    member x.name with get() = _name and set(v) = _name <- v

Is there an easier way to create a class or type to pass to a generic method?

Here is how it is called:

use db = Mongo.Create("mongodb://127.0.0.1:27017/test")
let col = db.GetCollection<products开发者_如何学JAVA>()
let count = col.Find() |> Seq.length
printfn "%d" count


Have you tried a record type?

type products = {
    mutable _id : ObjectId
    mutable name : string
    }

I don't know if it works, but records are often good when you just need a class that is basically 'a set of fields'.


Just out of curiosity, you can try adding a parameter-less constructor to a record. This is definitely a hack - in fact, it is using a bug in the F# compiler - but it may work:

type Products = 
  { mutable _id : ObjectId
    mutable name : string }
  // Horrible hack: Add member that looks like constructor 
  member x.``.ctor``() = ()

The member declaration adds a member with a special .NET name that is used for constructors, so .NET thinks it is a constructor. I'd be very careful about using this, but it may work in your scenario, because the member appears as a constructor via Reflection.

If this is the only way to get succinct type declaration that works with libraries like MongoDB, then it will hopefuly motivate the F# team to solve the problem in the future version of the language (e.g. I could easily imagine some special attribute that would force F# compiler to add parameterless constructor).


Here is a pretty light way to define a class close to your C# definition: it has a default constructor but uses public fields instead of getters and setters which might be a problem (I don't know).

type products =
    val mutable _id: ObjectId
    val mutable name: string
    new() = {_id = ObjectId() ; name = ""}

or, if you can use default values for your fields (in this case, all null):

type products() =
    [<DefaultValue>] val mutable _id: ObjectId
    [<DefaultValue>] val mutable name: string
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜