Я сталкиваюсь с случаями использования, когда количество строк, возвращаемых считывателем данных, может стать проблематичным в отношении потребления памяти.Следующий код использует JsonWriter (из JSON.NET) поверх потока.Можно, конечно, обсуждать полезность огромных документов JSON, но иногда наши варианты использования диктуются другими: -)
Несколько замечаний:
- Мой SqlDataReader может содержать несколько наборов результатов ('tables')
- Возможно, я отправляю вывод в поток FileStream или HttpResponse
- Я "абстрагировал" имена моих объектов, чтобы соответствовать первому столбцу, возвращенному для набора результатов
- Из-за возможности больших наборов результатов я использую асинхронные методы SqlDataReader.
- Я позволяю JSON.NET обрабатывать все проблемы сериализации фактических данных, содержащихся в результатах чтения данных.
Код:
var stream = ... // In my case, a FileStream or HttpResponse stream
using (var writer = new JsonTextWriter(new StreamWriter(stream)))
{
writer.WriteStartObject();
do
{
int row = 0;
string firstColumn = null;
while (await reader.ReadAsync())
{
if (row++ == 0)
{
firstColumn = reader.GetName(0);
writer.WritePropertyName(string.Format("{0}Collection", firstColumn));
writer.WriteStartArray();
}
writer.WriteStartObject();
for (int i = 0; i < reader.FieldCount; i++)
{
if (!reader.IsDBNull(i)) {
writer.WritePropertyName(reader.GetName(i));
writer.WriteValue(reader.GetValue(i));
}
}
writer.WriteEndObject();
}
writer.WriteEndArray();
} while (await reader.NextResultAsync());
writer.WriteEndObject();
}
Примером гетерогенного выхода будет:
{
"ContactCollection": {
"ContactItem": [{
"ContactID": "1",
"Contact": "Testing",
},
{
"ContactID": "2",
"Contact": "Smith, John",
},
{
"ContactID": "4",
"Contact": "Smith, Jane",
}
],
"MessageItem": [{
"MessageID": "56563",
"Message": "Contract Review Changed",
},
{
"MessageID": "56564",
"Message": " Changed",
},
{
"MessageID": "56565",
"Message": "Contract Review - Estimated Completion Added.",
}
]
}
}
Ссылка: