如果反序列化失败,则跳过 Cosmos DB 容器中的文档
Skip document in Cosmos DB container if the deserialization fails
我有以下代码用于从 Cosmos DB 容器中读取文档:
var result = new List<StoredLead>();
var linqSerializerOptions = new CosmosLinqSerializerOptions
{
PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
};
var iterator = container.GetItemLinqQueryable<StoredLead>(false, null, null, linqSerializerOptions).Where(expression).ToFeedIterator();
while (iterator.HasMoreResults)
{
var list = await iterator.ReadNextAsync();
foreach (var lead in list)
{
//Do some stuff with the lead
result.Add(lead);
}
}
return result;
如果 JSON 文档在任何字段中的值不正确(字符串而不是 int,或 int 而不是 date/time),我会得到 Newtonsoft.Json.JsonReaderException
,这会导致读取整批对象从要丢弃的容器中。请问是否可以跳过不能反序列化的文档,继续反序列化成功的文档
我尝试使用以下代码创建自定义 CosmosSerializer
:
public class SerliarizationService : CosmosSerializer
{
private readonly JsonSerializer serializer;
private readonly ILogger _logger;
public SerliarizationService(ILogger logger)
{
_logger = logger;
serializer = new JsonSerializer
{
NullValueHandling = NullValueHandling.Ignore
};
serializer.Error += HandleError;
}
private void HandleError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
{
// only log an error once
if (args.CurrentObject == args.ErrorContext.OriginalObject)
{
_logger.LogError("Error while deserializing document. Error message: {errorMessage}", args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
}
}
即当发生反序列化异常时,我尝试记录并抑制错误,但行为并不完全如我所愿。好像给不能成功反序列化的字段设置了默认值,这不是我想要实现的。
以下应该有效:
var iterator = container.GetItemLinqQueryable<StoredLead>()
.Where(x => x.PartitionKey == "example")
.Select(x => (object) x)
.Select(x => (JToken) x)
.ToFeedIterator();
var results = new List<StoredLead>();
while (iterator.HasMoreResults)
{
foreach (var item in await iterator.ReadNextAsync())
{
try
{
results.Add(item.ToObject<StoredLead>());
}
catch
{
//no implementation
}
}
}
通过 return 将该项目作为 JToken
您可以对其进行迭代并分别反序列化每个条目。 Select
语句允许您使用强类型的 linq 表达式,但仍然 return 查询结果作为 JToken
.
我有以下代码用于从 Cosmos DB 容器中读取文档:
var result = new List<StoredLead>();
var linqSerializerOptions = new CosmosLinqSerializerOptions
{
PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
};
var iterator = container.GetItemLinqQueryable<StoredLead>(false, null, null, linqSerializerOptions).Where(expression).ToFeedIterator();
while (iterator.HasMoreResults)
{
var list = await iterator.ReadNextAsync();
foreach (var lead in list)
{
//Do some stuff with the lead
result.Add(lead);
}
}
return result;
如果 JSON 文档在任何字段中的值不正确(字符串而不是 int,或 int 而不是 date/time),我会得到 Newtonsoft.Json.JsonReaderException
,这会导致读取整批对象从要丢弃的容器中。请问是否可以跳过不能反序列化的文档,继续反序列化成功的文档
我尝试使用以下代码创建自定义 CosmosSerializer
:
public class SerliarizationService : CosmosSerializer
{
private readonly JsonSerializer serializer;
private readonly ILogger _logger;
public SerliarizationService(ILogger logger)
{
_logger = logger;
serializer = new JsonSerializer
{
NullValueHandling = NullValueHandling.Ignore
};
serializer.Error += HandleError;
}
private void HandleError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
{
// only log an error once
if (args.CurrentObject == args.ErrorContext.OriginalObject)
{
_logger.LogError("Error while deserializing document. Error message: {errorMessage}", args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
}
}
即当发生反序列化异常时,我尝试记录并抑制错误,但行为并不完全如我所愿。好像给不能成功反序列化的字段设置了默认值,这不是我想要实现的。
以下应该有效:
var iterator = container.GetItemLinqQueryable<StoredLead>()
.Where(x => x.PartitionKey == "example")
.Select(x => (object) x)
.Select(x => (JToken) x)
.ToFeedIterator();
var results = new List<StoredLead>();
while (iterator.HasMoreResults)
{
foreach (var item in await iterator.ReadNextAsync())
{
try
{
results.Add(item.ToObject<StoredLead>());
}
catch
{
//no implementation
}
}
}
通过 return 将该项目作为 JToken
您可以对其进行迭代并分别反序列化每个条目。 Select
语句允许您使用强类型的 linq 表达式,但仍然 return 查询结果作为 JToken
.