在ASP.NET中提取多个记录集时的DataReader或DataSet

时间:2008-10-07 20:32:56

标签: asp.net performance dataset sqldatareader

我有一个ASP.NET页面,其中包含一些需要填充的控件(例如下拉列表)。

我想单独前往数据库并带回多个记录集,而不是为每个控件进行往返。

我可以在DataSet中带回多个表,或者我可以带回一个DataReader并使用'.NextResult'将每个结果集放入一个自定义的业务类中。

使用DataReader方法我是否可能看到足够大的性能优势,或者我应该只使用DataSet方法?

任何关于你通常如何处理这个问题的例子都将不胜感激。

10 个答案:

答案 0 :(得分:7)

  1. 如果您的数据库中有超过1000条记录。
  2. 如果你对此不感兴趣 自定义存储和自定义分页 “ For GridView
  3. 如果您的服务器有内存压力。
  4. 如果连接没问题 每次该页面都有您的DataBase 调用。
  5. 然后我认为更好的方法是使用DataReader。

    否则

    1. 如果您的数据库记录少于1000
    2. 如果您有兴趣 存储和分页“ For GridView的
    3. 如果您的服务器没有内存 应力。
    4. 如果你想连接到你的 DataBase只有一次得到了 缓存的好处。
    5. 然后我认为更好的是使用DataSet。

      我跳,我是对的。

答案 1 :(得分:4)

始终将您的数据放入为特定用途定义的类中。不要传递DataSet和DataReader。

答案 2 :(得分:4)

如果存储过程返回多个集合,请使用DataReader.NextResult前进到下一个数据块。这样,您可以获取所有数据,将其加载到对象,并尽快关闭阅读器。这将是获取数据的最快方法。

答案 3 :(得分:4)

即使已经有很多好的答案,看到没有答案已经标记出来,我想我也会增加两位。

我会使用DataReaders,因为它们的速度要快得多(如果性能是你的事情,或者你需要尽可能多的话)。我参与过的大多数项目在每个表格中都有数百万条记录,性能也是一个问题。

有些人说过跨层发送DataReader并不是一个好主意。我个人并不认为这是一个问题,因为“DbDataReader”在技术上与数据库无关(或不必)。也就是说,您可以在不需要数据库的情况下创建DbDataReader的实例。

为什么我这样做是出于以下原因: 经常(在Web应用程序中)您生成Html,Xml或JSON或其他数据转换。那么为什么从DaraReader转到某个POCO对象只是为了将它转换回XML或JSON并将其发送到网络中。这种过程通常需要3次转换和对象实例化的引导加载,只是几乎立即将它们抛弃。

在某些情况下,这很好或无法帮助。我的数据层通常为系统中的每个存储过程提供两种方法。一个返回DbDataReader,另一个返回DataSet / DataTable。返回DataSet / DataTable的方法调用返回DbDataReader的方法,然后使用DataTable的“Load”方法或适配器来填充数据集。有时您需要DataSet,因为您可能需要以某种方式重新调整数据的用途,或者您需要触发另一个查询,并且无法启用MARS,您无法打开DbDataReader并触发另一个查询。

现在使用DbDataReader或DataSet / DataTable存在一些问题,通常是代码清晰度,编译时检查等。您可以为datareader使用包装类,实际上您可以将DataReader与IEnumerable一起使用。真的很酷的能力。因此,您不仅可以获得强大的输入和代码可读性,而且还可以获得IEnumerable!

所以一个类可能看起来像这样。

public sealed class BlogItemDrw : BaseDbDataReaderWrapper
{
    public Int64 ItemId { get { return (Int64)DbDataReader[0]; } }
    public Int64 MemberId { get { return (Int64)DbDataReader[1]; } }
    public String ItemTitle { get { return (String)DbDataReader[2]; } }
    public String ItemDesc { get { if (DbDataReader[3] != DBNull.Value) return (String)DbDataReader[3]; else return default(String); } }
    public DateTime ItemPubdate { get { return (DateTime)DbDataReader[4]; } }
    public Int32 ItemCommentCnt { get { return (Int32)DbDataReader[5]; } }
    public Boolean ItemAllowComment { get { return (Boolean)DbDataReader[6]; } }
    public BlogItemDrw()
      :base()
    {
    }

    public BlogItemDrw(DbDataReader dbDataReader)
      :base(dbDataReader)
    {
    }
}

DataReader Wrapper

我有一篇博文(上面的链接),详细介绍了我将为这些和其他DataAccess图层代码制作源代码生成器。

您可以对DataTables使用相同的技术(代码生成器生成代码),因此您可以将它们视为强类型DataTable,而无需开箱即用的VS.NET提供的开销。

请记住,只有一个包装类的实例。所以你不是要创建数百个类的实例而只是抛弃它。

答案 4 :(得分:3)

将DataReader映射到中间对象,然后使用这些对象绑定控件。在某些情况下可以使用DataSet,但是当你有充分理由“只是获取数据”时,这些数据很少。无论你做什么,都不要将DataReader传递给你的控件来绑定(不是说你说你正在考虑这个)。

我个人的偏好是使用ORM,但是如果您要手动滚动数据访问,我认为您应该更喜欢将DataReader映射到使用DataSet的对象。使用.NextResult作为限制自己多次击中数据库的方法是一把双刃剑,但是明智地选择。如果您尝试创建只使用一次数据库调用就能获得所需内容的过程,您会发现自己会重复自己。如果您的应用程序只有几页,那可能没问题,但事情很快就会失控。就个人而言,我宁愿每个对象类型有一个proc,然后多次命中数据库(每个对象类型一次),以便最大限度地提高可维护性。这是一个ORM闪耀的地方,因为一个好的将产生Sql,在大多数情况下,它会通过一次调用获得你想要的东西。

答案 5 :(得分:2)

如果您对更新或删除从数据库中提取的记录不感兴趣,我建议您使用DataReader。基本上DataSet内部使用多个Datareaders,因此DataReader应该为您提供良好的性能优势。

答案 6 :(得分:2)

几乎在所有情况下DataReader s are the best solution都可以从数据库中读取。 DataReaderfaster,所需内存少于DataTableDataSet s。

此外,DataSet通常会导致OO模型为broken的情况。传递关系数据/模式而不是知道如何操作数据的对象,这不是面向对象的。

因此,出于可扩展性,可伸缩性,模块性和性能原因,如果您认为自己是Real Programmer™,请始终使用DataReader;)

在实践和理论中检查有关事实和讨论的链接。

答案 7 :(得分:2)

无论您是在获取单个结果集还是多个结果集,无论是使用DataReader而不是DataSet,都会达成共识。

关于你是否曾经打扰多个结果集,智慧是你不应该,但我可以设想一个合理的例外类别:(紧紧地)相关的结果集。您当然不希望添加查询以返回在应用程序中数百甚至数十页上重复的下拉列表的同一组选项,但可以合理地组合使用狭义的几组。例如,我目前正在创建一个页面,以显示一批ETL数据的“差异”。这些查询都不可能在其他地方使用,因此将它们封装为单个“获取差异”特征是很方便的。另一方面,与处理ORM或手动数据访问代码的自然单一结果集架构相比,这样做的更好性能可能是微不足道的。

答案 8 :(得分:1)

我已经找到了一个使用DataReaders进行所有调用的方法,我注意到了显着的性能提升,特别是在我加载下拉列表的情况下,以及其他类似的简单项目。

就个人而言,有多个下拉菜单,我通常会去绘制单个数据块来获取它,而不是说一个返回5个结果集的存储过程。

答案 9 :(得分:0)

查看.NET 2.0及更高版本提供的TableAdapter。他们所做的是为您提供强类型DataTable的强度,并允许您将Fill方法映射到将使用DataReader加载它的方法。您的填充方法可以是现有的存储过程,您自己的AdHoc SQL,甚至可以让向导为您生成AdHod或存储过程。

您可以通过在项目中启动新的XSD DataSet对象来找到它。对于不仅用于查找的表,您还可以将插入/更新/删除方法映射到TableAdapter。