使用IEnumerable <T>返回类型的SQL数据是否有任何陷阱?

sco*_*ttm 5 c# sql-server ienumerable

我的问题是关于SQL连接状态,负载等基于以下代码:

public IEnumberable<MyType> GetMyTypeObjects()
{
  string cmdTxt = "select * from MyObjectTable";

  using(SqlConnection conn = new SqlConnection(connString))
  {
    using(SqlCommand cmd = new SqlCommand(cmdTxt, conn))
    {
      conn.Open();
      using(SqlDataReader reader = cmd.ExecuteReader())
      {
         while(reader.Read())
         {
            yield return Mapper.MapTo<MyType>(reader);
         }
       }
    }
  }
  yield break;
}
Run Code Online (Sandbox Code Playgroud)

我可以看到这可能是一个问题,如果有许多进程在IEnumerable对象的迭代之间运行类似的代码,执行时间长,因为连接将打开更长时间等等.但是,这似乎也可能会降低CPU使用率在SQL服务器上,因为它只在使用IEnumerable对象时返回数据.它还降低了客户端上的内存使用量,因为客户端只需在其工作时加载一个MyType实例,而不是加载所有出现的MyType(通过迭代整个DataReader并返回List或其他内容).

  • 您是否有任何实例可以想到您不希望以这种方式使用IEnumerable,或者您认为它完全适合的任何实例?

  • 这会给SQL服务器带来什么样的负载?

  • 这是你在自己的代码中使用的东西(除非提及NHibernate,Subsonic等)吗?

  • -

Ada*_*son 6

这不是我要遵循的模式.我不会像在锁定时那样担心服务器上的负载.遵循这种模式将数据检索过程集成到您的业务逻辑流程中,这似乎是一个全面解决问题的方法; 你不知道在迭代方面会发生什么,而你正在插入它.一次性检索您的数据,然后在关闭阅读器后允许客户端代码对其进行枚举.


Guf*_*ffa 2

我不会使用它,因为它隐藏了正在发生的事情,并且它可能会在没有适当处理的情况下留下数据库连接。

当您读取完最后一条记录后,连接对象将被关闭,如果您在此之前停止读取,连接对象将不会被释放。例如,如果您知道结果中始终有 10 条记录,并且只有一个循环从枚举器读取这 10 条记录,而不进行第十一次读取超出最后一项的 Read 调用,则连接不会正确关闭。另外,如果您只想使用结果的一部分,则无法在不读取其余记录的情况下关闭连接。

即使您正确地使用了枚举器的内置扩展,也可能会导致这种情况:

foreach (MyType item in GetMyTypeObjects().Take(10)) {
   ...
}
Run Code Online (Sandbox Code Playgroud)