当我尝试返回元组时,IDataReader 已关闭
Posted
技术标签:
【中文标题】当我尝试返回元组时,IDataReader 已关闭【英文标题】:IDataReader is closed when I try to return a tuple 【发布时间】:2020-07-11 10:49:38 【问题描述】:我正在尝试返回一个 HTTP 响应,其中包含我从数据库中选择的记录数组。但我无法将我的IDataReader
映射到Enumerable
。这是我的代码中相关的部分:
namespace Web.Api.Controllers
public static class Blah
public static IEnumerable<T> Select<T>(this IDataReader reader,
Func<IDataReader, T> projection)
while (reader.Read())
yield return projection(reader);
[HttpPost]
[Route("Search")]
public async Task<Tuple<int, IEnumerable<CustomerViewModel>, int>> Search([FromBody]CustomerViewModel model)
var s = _configuration.GetConnectionString("DefaultConnectionAlt");
using (SqlConnection connection = new SqlConnection(s))
connection.Open();
using (SqlCommand command = new SqlCommand("Search @RegistrationDate=\"2020-07-09\"", connection))
using (IDataReader reader = command.ExecuteReader())
var results = reader.Select<CustomerViewModel>(CustomerViewModel.Create);
return Tuple.Create(0, results, 29);
当我向http://localhost:42432/api/Search
发送 POST 请求时,while (reader.Read())
行给出了错误:
System.InvalidOperationException: 'Invalid attempt to call Read when reader is closed.'
我在return Tuple.Create(0, results, 29);
放置了一个断点,当我检查results
变量时,它显示了我期望的结果。但是在我跳出那个断点之后,我在while (reader.Read())
上得到了错误。
谁能告诉我如何解决我的问题?
我正在关注此处列出的示例:
How can I easily convert DataReader to List<T>?
Convert rows from a data reader into typed results
编辑 - 我正在使用 dotnetcore
【问题讨论】:
请说明您使用的 skd 版本(.net framework 还是 dot net core)? @NicklausBrain 我编辑了我的问题,说我正在使用 dot net core 这能回答你的问题吗? What are the benefits of a Deferred Execution in LINQ? 【参考方案1】:您看到的是使用IEnumerable
时deferred execution 的效果,在本例中,是从您的Select
方法返回的IEnumerable<T>
。
您将返回一个 IEnumerable<CustomerViewModel>
作为元组的一部分,此时尚未执行。然后通过using
的使用来处理连接和阅读器。
当您随后在方法返回后尝试迭代 IEnumerable<CustomerViewModel>
时,捕获的数据读取器已作为处置的一部分关闭。
当您通过调试器进行检查时,Results
是一种迭代可枚举的方法,此时尚未释放数据读取器。
防止这种情况的一种选择是在您返回之前在您的results
上调用ToList
。
这与 javascript 中的生成器概念类似。
【讨论】:
【参考方案2】:请记住,IEnumerable
是按需延迟处理的。
在您的特定情况下,Search
返回带有尚未读取的IEnumerable
的元组值。
因此reader
在IEnumerable
被填充之前被关闭。
【讨论】:
以上是关于当我尝试返回元组时,IDataReader 已关闭的主要内容,如果未能解决你的问题,请参考以下文章
使用3个元素元组时为什么会出现CombineByKey错误?