简体   繁体   English

使用NoRM从F#访问MongoDB

[英]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. 从F#中测试NoRM https://github.com/atheken/NoRM ,并尝试找到一种使用它的好方法。 Here is the basic C#: 这是基本的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#: 可以,但是这是我从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>()
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: 这绝对是黑客-实际上,它使用的是F#编译器中的错误-但这可能有效:

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. member声明添加了一个具有特殊.NET名称的成员,该member用于构造函数,因此.NET认为它是构造函数。 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 (eg I could easily imagine some special attribute that would force F# compiler to add parameterless constructor). 如果这是获得与MongoDB这样的库一起使用的简洁类型声明的唯一方法,那么它将有希望激励F#团队在未来版本的语言中解决问题(例如,我可以很容易地想象一些强制F#的特殊属性)编译器添加无参数构造函数)。

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). 这是一种定义接近C#定义的类的简便方法:它具有默认构造函数,但使用公共字段而不是getter和setter,这可能是个问题(我不知道)。

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): 或者,如果您可以使用字段的默认值(在这种情况下,全部为null):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM