微软的Orleans在其Sample Projects中给出了一个连接MongoDB作为其存储提供程序(Storage Provider)的案例。
为了连接Mongo,你需要用NuGet下载“Official MongoDB C# Driver”驱动。这个插件是由10Gen, Inc提供的。
首先你需要下载和安装MongoDB的windows版本。下载地址为:
https://www.mongodb.org/dr/fastdl.mongodb.org/win32/mongodb-win32-x86_64-3.2.4-signed.msi/download
通过在存储服务中保存数据,自定义的存储提供程序使你能够扩展Orleans的能力。本例中,我们将数据保存在文件系统和MongoDB中。
虽然二进制的数据在数据持久化方面通常性能更好,本例仍旧使用了JSON格式,因为其具有更好的可读性和易于校验,这对于代码范例来说很重要。在实际应用中,可能你会自行决定是否要采用其它的序列化方式。
运行范例
范例工程包括4个项目:存储提供程序库,3个测试库,解决方案结构与HelloWorld范例相同。
注意:Orleans范例代码中都是NewtonSoft.Json version 7.0.0的,实际运行调试的之前你需要用Nuget更新一下最新的插件。我的是8.0.2版本。
先把DevTestServerConfiguration.xml文件中的存储提供程序相关的注释去掉:
编译,调试运行Test.Client项目(请注意输入的文本结果):
Successfully started Orleans silo 'host-001' as a Primary node.
We just wrote something to the persistent store. Please verify!
Orleans Silo is running.
Press Enter to terminate...
停止调试,定位到Test.Client项目的bin\Debug文件夹下,会发现多出来一个Samples.FileStorage文件夹:
开启命令行窗口,定位到Test.Client\bin\Debug\Samples.FileStorage目录下,用more命令查看文件的详细信息,能够看到其中的JSON内容:
然后我们再次重新启动客户端程序。现在由于Orleans的状态保持机制,输出的内容与上一次调试运行的结果就不一样了:
This was found in the persistent store: John, Doe, Male
Orleans Silo is running.
Press Enter to terminate...
如果你是安装了MongoDB来作为存储提供程序,你可以重复上一个过程以测试数据库来实现状态保持机制。注意改写一下DevTestServerConfiguration.xml中的配置信息,并确保Mongod.exe进程在运行中。如果用Mongo.exe检查数据,你可以看到:
MongoDB shell version: 2.4.6
connecting to: test
> use orleanssamples
switched to db orleanssamples
> db.PersonState.find()
{ "_id" : ObjectId("533391afcf20b011307a82bf"), "FirstName" : "John", "LastName" : "Doe", "Gender" : 0, "key" : "0000000000000000000000000000000003ffffffc0950639" }
>
(译者注:以下是实际运行一个远程MongoDB的结果截屏)
设计
BaseJSONStorageProvider包含了JSON的序列化和反序列化代码,实现了IStorageProvider接口的几个主要接口方法,Init(),ReadStateAsync()
,WriteStateAsync()和
ClearStateAsync()。
与数据层进行交换的逻辑委托给了DataManager类层次结构,包括IJSONStateDataManager,
GrainFileStateManager
, 和GrainStateMongoDataManager
.这些类的Delete,Read和Write方法直接对应了存储提供程序类的相应方法。
本例中没有涉及通过.NET与文件系统或者MongoDB进行交互的细节,这将中其它地方讨论。不过,仍旧需要解释几点。
中两个例子中,grain类型的名字被用于实例集合的命名;在文件存储的例子中,集合名称与存储数据的文件夹名称相对应,而其主键则指明了特定的实例。在MongoDB的例子中,grain类型名代表了一个数据库集合,而主键则用于特定的文件名。
在MongoDB的例子中,在带有键值的写操作时JSON的结构被增强了,增加了一个元素,key,其中包含了grain的键值并使我们可以在读操作时查询相应的文件。此外,Mongo内带用于文档识别的_id参数也被仔细处理。
public Task Write(string collectionName, string key, string entityData) { var collection = GetOrCreateCollection(collectionName); var query = Query.EQ("key", key); var existing = collection.FindOne(query); var doc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize(entityData); doc["key"] = key; if ( existing == null ) { collection.Insert(doc); } else { doc["_id"] = existing["_id"]; collection.Update(query, Update.Replace(doc)); } return TaskDone.Done; }
在进行读操作时,_id字段从发回给调用方的JSON文档中去除,因为此字段不包含在Orleans的数据模型中。
public Task Read(string collectionName, string key)
{
var collection = GetCollection(collectionName);
if (collection == null)
return Task.FromResult(null);
var query = Query.EQ("key", key);
var existing = collection.FindOne(query);
if (existing == null)
return Task.FromResult(null);
existing.Remove("_id");
existing.Remove("key");
var strwrtr = new System.IO.StringWriter();
var writer = new MongoDB.Bson.IO.JsonWriter(strwrtr, new MongoDB.Bson.IO.JsonWriterSettings());
MongoDB.Bson.Serialization.BsonSerializer.Serialize(writer, existing);
return Task.FromResult(strwrtr.ToString());
}
原文链接:
http://dotnet.github.io/orleans/Samples-Overview/Storage-Providers