我有一个webapi,它从数据库列转换后返回一些protobuf-net序列化项。项目的数量可能相当大,所以我想避免在内存中实现它们而不是将它们流出来,但是,在我的Stream抛出已经处理的异常之前,我从来没有得到过一个。如果我实现列表它确实有效,但我想避免它。 这就是我正在做的事情::
private override async Task<IEnumerable<MyObj>> GetRawData(int id)
{
using(var sqlConn = GetOpenConnection())
{
using (var sqlReader =(await sqlConn.ExecuteReaderAsync(
_workingQuery,new {id = id}, 60)
.ConfigureAwait(false) as SqlDataReader))
{
await sqlReader.ReadAsync().ConfigureAwait(false);
using (var stream = sqlReader.GetStream(0))
{
return _serializerModel.DeserializeItems<MyObj>(stream, PrefixStyle.Base128, 1)
}
}
}
}
private async Task<IHttpActionResult> TransformData(int id)
{
var data=await GetRawData().ConfigureAwait(false);
return Ok(new {Data=data.Where(m=>...).Select(m=>...)})
}
[HttpGet,Route("api/myroute/{id}"]
public async Task<IHttpActionResult> GetObjs(int id)
{
return await TransformData();
}
然而,我最终收到有关阅读已处置流的错误。如何避免此错误?
答案 0 :(得分:1)
这一行
return _serializerModel.DeserializeItems<MyObj>(stream, PrefixStyle.Base128, 1)
只返回索引器。您似乎意识到结果尚未实现。但是,在返回后,using
块会处理您的Stream
。
解决方案是让GetRawData
返回 Stream 。然后,在TransformData
内using
内的Stream
内,您反序列化,过滤并返回结果。
第二个潜在问题是您当前的方法会处理整个结果,然后立即将其发送给客户端。
要让 Web API 发送流式搜索结果,您需要使用HttpResponseMessage
,并将Stream
传递给它的Content
媒体资源
以下是一个例子:http://weblogs.asp.net/andresv/asynchronous-streaming-in-asp-net-webapi
如果您想将Stream
流式传输到另一个Stream
(我知道,这听起来很有趣),您需要保持ReaderStream
打开,直到WriterStream
完成写作。这是一个高级代表:
using (ReaderStream)
{
using (WriterStream)
{
// write object from ReaderStream to WriterStream
}
}
答案 1 :(得分:1)
它的长短是你返回一个非枚举序列,并在它到达调用者之前关闭(处理)它所需的一切。您将需要:
.ToList()
对于后者,我很想在中心部分使用迭代器块(在所有await
之后)。类似的东西:
bool dispose = true;
SqlConnection conn = null;
//...others
try {
conn = ...
...await...
var result = InnerMethod(conn, stream, ..., )
// ^^^ everything now known / obtained from DB
dispose = false; // handing lifetime management to the inner method
return result;
} finally {
if(dispose) {
using(conn) {}
//.//
}
}
IEnumerable<...> Inner(...) { // not async
using (conn)
using (stream) {
foreach(var item in ...) {
yield return item;
}
}
}