我在Azure中使用Cosmos DB的DocumentDB API。文档从EventHub获取,并由EventHub触发的Azure功能存储到数据库。
我正在保存的文档也包含几个枚举。不幸的是,这些枚举值是使用它们的索引号而不是枚举值序列化的(参见这里:https://i.stack.imgur.com/3nP9o.png)。或者,更准确地说,这是在Azure中运行该函数时发生的情况。本地IDE中的测试工作正常。
这是写给Cosmos / DocumentDB的代码:
DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey);
...
var response = DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), tick);
response.Wait();
“tick”是要存储的上述对象。
我尝试了一些方法来使文档客户端正确序列化枚举:
枚举属性中的注释:
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
public OrderActionEnum? Action { get; set; }
enum defintion的注释:
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
public enum OrderActionEnum
{
NEW,
CHANGE,
DELETE,
SNAPSHOT,
INITIAL
}
将转换器传递给文档db client的构造函数:
DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey,
new JsonSerializerSettings
{
Converters = new List<JsonConverter> {new StringEnumConverter()}
});
设置默认序列化程序:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> {new StringEnumConverter()}
};
这些尝试都没有说服Cosmos / DocumentDB存储枚举值。
一个有趣的影响是第三个变体(将转换器传递给DocumentClient的构造函数)在运行Azure时导致异常(本地测试工作正常):
2017-11-24T15:08:55.291 System.MissingMethodException : Method not found: 'Void Microsoft.Azure.Documents.Client.DocumentClient..ctor(System.Uri, System.String, Newtonsoft.Json.JsonSerializerSettings, Microsoft.Azure.Documents.Client.ConnectionPolicy, System.Nullable`1<Microsoft.Azure.Documents.ConsistencyLevel>)'.
at TickAnalysis.DataManager.Persistency.AbstractCosmosClient`1..ctor(ILogger logger,String dbServiceEndpoint,String dbAuthKey,String databaseId,String collectionId)
at TickAnalysis.DataManager.DataManagerFunction.RunStoreOrderEvent(String message,TraceWriter log)
这看起来有点像正在使用的Microsoft.Azure.DocumentDB包的不同版本。因此,我将本地bin中的DLL与Azure中为该函数部署的DLL进行了比较。在这两种情况下都是版本1.19.1。
现在我的想法已经不多了。我可以用普通字符串替换枚举,但我真的不想这样做。任何提示都表示赞赏。
我知道之前有过类似的问题。例如:
不幸的是,这些都没有解决我的问题。
答案 0 :(得分:1)
我找到了解决问题的解决方法:
代码如下所示:
DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey);
...
var jsonString = JsonConvert.SerializeObject(tick);
var jObject = JsonConvert.DeserializeObject(jsonString);
var response = DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), jObject);
response.Wait();
通过这种方法将枚举转换为纯字符串。不是很好,但毕竟我很满意这个解决方案。至少我不需要改变任何其他地方。
答案 1 :(得分:0)
您应该使用Azure Functions Cosmos DB输出绑定来保存文档。以下示例按预期工作(将枚举值保存为字符串)。
代码run.csx
:
#r "Newtonsoft.Json"
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class Doc
{
public string id { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public OrderActionEnum Action { get; set; }
}
public enum OrderActionEnum { NEW, CHANGE }
public static HttpResponseMessage Run(HttpRequestMessage req, out Doc outputDocument)
{
outputDocument = new Doc { id = "111", Action = OrderActionEnum.CHANGE };
return req.CreateResponse(HttpStatusCode.OK);
}
绑定function.json
:
{
"bindings": [
{
"authLevel": "function",
"name": "req",
"type": "httpTrigger",
"direction": "in"
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"type": "documentDB",
"name": "outputDocument",
"databaseName": "testdb",
"collectionName": "test",
"createIfNotExists": false,
"connection": "my_DOCUMENTDB",
"direction": "out"
}
],
"disabled": false
}
制作文件:
{
"id": "111",
"Action": "CHANGE"
}