Использование NoRM для доступа к MongoDB из F # - PullRequest
0 голосов
/ 28 ноября 2010

Тестирование NoRM https://github.com/atheken/NoRM из F # и попытка найти хороший способ его использования. Вот основной 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());
}

Это работает нормально, но вот как я получаю к нему доступ из 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

Есть ли более простой способ создать класс или тип для передачи в универсальный метод?

Вот как это называется:

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

Ответы [ 3 ]

1 голос
/ 29 ноября 2010

Просто из любопытства вы можете попробовать добавить конструктор без параметров в запись. Это определенно хак - на самом деле он использует ошибку в компиляторе F # - но он может работать:

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

Объявление member добавляет член со специальным именем .NET, которое используется для конструкторов, поэтому .NET считает, что это конструктор. Я буду очень осторожен в использовании этого, но это может работать в вашем сценарии, потому что элемент отображается как конструктор через Reflection.

Если это единственный способ получить сжатое объявление типа, которое работает с библиотеками, такими как MongoDB, то это, вероятно, побудит команду F # решить проблему в будущей версии языка (например, я мог бы легко представить какой-то специальный атрибут, который заставит компилятор F # добавить конструктор без параметров).

1 голос
/ 28 ноября 2010

Вы пробовали тип записи?

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

Я не знаю, работает ли он, но записи часто бывают хорошими, когда вам просто нужен класс, который по сути является "набором полей".

0 голосов
/ 28 ноября 2010

Вот довольно легкий способ определить класс, близкий к вашему определению C #: он имеет конструктор по умолчанию, но использует открытые поля вместо методов получения и установки, что может быть проблемой (я не знаю).

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

или, если вы можете использовать значения по умолчанию для ваших полей (в данном случае, все null):

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