使用MongoDB C#驱动程序处理集合事件(v2.0)

时间:2015-05-11 09:07:12

标签: c# mongodb

使用新的MongoDB驱动程序(v2.0)一直非常具有挑战性。您在Web上找到的大多数示例仍然是指旧版驱动程序。官方Mongo网站上的The reference manual for v2.0至少可以说是简洁的。

我试图做一件简单的事情:检测集合何时被更改以便将C#事件转发到我的服务器应用程序

为此,我发现以下C#example(见下文)我试图转换为新的API。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace TestTailableCursor {
    public static class Program {
        public static void Main(string[] args) {
            try {
                var server = MongoServer.Create("mongodb://localhost/?safe=true");
                var database = server["test"];

                if (database.CollectionExists("capped")) {
                    database.DropCollection("capped");
                }
                var collectionOptions = CollectionOptions.SetCapped(true).SetMaxDocuments(5).SetMaxSize(10000);
                var commandResult = database.CreateCollection("capped", collectionOptions);
                var collection = database["capped"];

                // to test the tailable cursor manually insert documents into the test.capped collection
                // while this program is running and verify that they are echoed to the console window

                // see: http://www.mongodb.org/display/DOCS/Tailable+Cursors for C++ version of this loop
                BsonValue lastId = BsonMinKey.Value;
                while (true) {
                    var query = Query.GT("_id", lastId);
                    var cursor = collection.Find(query)
                        .SetFlags(QueryFlags.TailableCursor | QueryFlags.AwaitData)
                        .SetSortOrder("$natural");
                    using (var enumerator = (MongoCursorEnumerator<BsonDocument>) cursor.GetEnumerator()) {
                        while (true) {
                            if (enumerator.MoveNext()) {
                                var document = enumerator.Current;
                                lastId = document["_id"];
                                ProcessDocument(document);
                            } else {
                                if (enumerator.IsDead) {
                                    break;
                                }
                                if (!enumerator.IsServerAwaitCapable) {
                                    Thread.Sleep(TimeSpan.FromMilliseconds(100));
                                }
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }

            Console.WriteLine("Press Enter to continue");
            Console.ReadLine();
        }

        private static void ProcessDocument(BsonDocument document) 
        {
            Console.WriteLine(document.ToJson());
        }
    }
}

一些(相关)问题:

  1. 这是新驱动程序的正确方法吗?
  2. 如果是这样,我如何设置集合选项(如上例中的SetCap)。新的API包含了一些名为&#34; CollectionSettings&#34;的东西,似乎完全如此 无关。
  3. 我唯一依赖传统驱动程序的选择吗?
  4. 感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

  

我唯一的选择是依靠传统驱动程序吗?

没有

  

[...]如何设置集合选项(如上例中的SetCap)。新的API包含一个名为“CollectionSettings”的东西,它似乎完全不相关。

现在有CreateCollectionSettingsCollectionSettings是驱动程序的设置,即指定每个集合的默认行为的方法。 CreateCollectionOptions可以像这样使用:

db.CreateCollectionAsync("capped", new CreateCollectionOptions 
      { Capped = true, MaxDocuments = 5, MaxSize = 10000 }).Wait();
  

这是新驱动程序的正确方法吗?

我认为,tailable游标是数据库的一个特性,避免轮询总是有意义的。

我转换了代码的要点,似乎可以在我的机器上运行™:

在网络或UI应用程序中careful when using .Result and .Wait()

private static void ProcessDocument<T>(T document)where T : class
{
    Console.WriteLine(document.ToJson());
}

static async Task Watch<T>(IMongoCollection<T> collection) where T: class
{ 
    try {
        BsonValue lastId = BsonMinKey.Value;
        while (true) {
            var query = Builders<T>.Filter.Gt("_id", lastId);

            using (var cursor = await collection.FindAsync(query, new FindOptions<T> { 
                CursorType = CursorType.TailableAwait, 
                Sort = Builders<T>.Sort.Ascending("$natural") }))
            {
                while (await cursor.MoveNextAsync())
                {
                    var batch = cursor.Current;
                    foreach (var document in batch)
                    {
                        lastId = document.ToBsonDocument()["_id"];
                        ProcessDocument(document);
                    }
                }
            }
        }
    }
    catch (Exception ex) {
        Console.WriteLine("Unhandled exception:");
        Console.WriteLine(ex);
    }
}