请问把数据转换成实体类用datareader好还是dataset好?大家平时用哪个?

mvcmvcmvc2 2011-09-25 09:32:43
平时 数据都是用实体类 或者ILIST<实体类>

所以涉及到一个 数据转换为实体~

请问只是用来转换为实体对象 或者LIST<实体类> 集合

用 datareader 好 还是 dataset好呢~ 说下原因 谢谢~~

datareader 只读向前 速度快

可是周公 这篇文章 测试发现

http://zhoufoxcn.blog.51cto.com/792419/614794

datatable 快~ 问问大家平时用的哪个~ 谢谢
...全文
566 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
或者这样说吧,假设它的结论是成立的,既避免GetValue语句就可以提高10倍速度,那么我们几乎可以猜测,完全不使用反射的SetValue语句,从DbDataReader取得目标对象,最终测试结果可以提高几乎100倍的速度。
  • 打赏
  • 举报
回复
它使用了 row[item.Key] 来避免 GetValue 语句。所以你看,即使仍然使用 SetValue 语句来反射设置对象属性(而不是说哦那个Convert一举两得),测试数据也已经说明,“有一个数量级的速度差别”(原文的结论)。
xufeizhi254 2011-09-26
  • 打赏
  • 举报
回复
其实是相对来说的。如果数据量读取大的话,datareader要好。由于dataset它要读到内存中,相对于现在来说内存比较大,配置高,你感觉不出来,肯定觉得它不影响了。dataset感觉读取数据方便,可以随意取。还可以存取多表吧!
gengchenhui 2011-09-26
  • 打赏
  • 举报
回复
wslkspdhfd
mvcmvcmvc2 2011-09-26
  • 打赏
  • 举报
回复
多谢大家的回复 结贴~~

受教了~
danjiewu 2011-09-26
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 sp1234 的回复:]

引用 21 楼 danjiewu 的回复:
那个博客根本就是误导人的,adapter.Fill都不计算在耗时内那测试还有什么意义。实际上adapter.Fill也是通过datareader来读取数据库的。

博客中一开头实际要测试的是一个针对DataTable,另一个针对DbDataReader,仅仅对比这两个结构进行对象转换的时间。而它写了测试前者的时间的代码,并没有写后者的。并且它针对……
[/Quote]

他从DataTable转换为对象也是通过反射的,所以最后结果应该还是用DataReader快一些,当然差别是很小的。
单单比较DataTable和DbDataReader没意义,因为DataTable跟数据库完全无关,只是存放的从DbDataReader读取的数据
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 h_zai888 的回复:]
但是datareader 要注意关闭 close
[/Quote]

这个说法是不对的!

仅仅对于设置 CommandBehavior 为 CloseConnection 的 SqlDataReader 对象实例,并且当它已经离开了 Connection 控制变量的作用域(也就是说你的代码不可能去对其执行 Close()操作),你才需要通过执行 reader.Close() 来关闭Connection。其它的都是多余的,额外地占用了时间。

通用的DbDataReader根本没有 CommandBehavior,那么也根本没有这个机制。而就算是针对SqlDataReader,你也只有机器特定的情况下才有必要去想着调用其 Close() 方法。
  • 打赏
  • 举报
回复
因为文章虽然结论不对 --> 因为文章虽然总结的不对
h_zai888 2011-09-26
  • 打赏
  • 举报
回复
习惯实用dataset 但是datareader 要注意关闭 close
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 danjiewu 的回复:]
那个博客根本就是误导人的,adapter.Fill都不计算在耗时内那测试还有什么意义。实际上adapter.Fill也是通过datareader来读取数据库的。
[/Quote]
博客中一开头实际要测试的是一个针对DataTable,另一个针对DbDataReader,仅仅对比这两个结构进行对象转换的时间。而它写了测试前者的时间的代码,并没有写后者的。并且它针对后者,使用的是反射方式。

当然也确实,文章一开头看起来还是清楚表明了是要比较DataTable和DbDataReader转换为对象的方法测试。但是文章最后的实际测试却把它作为比较读取数据库记录成为对象的整体测试的结论来做总结了,而整体时间没有包括Fill方法和ExecuteReader的时间。

不过我们想象一下,就算包括了这两段时间,结论会改变吗?因为文章虽然结论不对,但是测试数据没有骗人,仍然可以说明:基于反射进行大量GetValue、SetValue的代码的性能往往是很差的。

请搜索一下代码中的“row[item.Key]”这个语句,这里是关键,这条语句不是使用反射,而是使用DataRow的从列中搜索的方式。因此我会写上面的内容,来个直截了当的也不反射的 ConvertFrom 设计来对比一下。
danjiewu 2011-09-26
  • 打赏
  • 举报
回复
那个博客根本就是误导人的,adapter.Fill都不计算在耗时内那测试还有什么意义。实际上adapter.Fill也是通过datareader来读取数据库的。
  • 打赏
  • 举报
回复
嗯当然,我们可以把接口里的那个方法写的更简单一点
public interface IConverterFromDbDataReader<T>
{
void ConvertFrom(DbDataReader reader);
}

public class FileTransferBlock : IConverterFromDbDataReader<FileTransferBlock>
{
public long CallID;
public string SourceFile;
public string TargetFile;
public long StartPosition;

public void ConvertFrom(DbDataReader reader)
{
this.CallID = (long)reader["call_id"];
this.SourceFile = (string)reader["source"];
this.TargetFile = (string)reader["target"];
this.StartPosition = (long)reader["position"];
}
}
static public List<T> GetRecords<T>(string sql, params DbParameter[] para) where T : IConverterFromDbDataReader<T>, new()
{
using (DbConnection conn = CreateNewConnection())
{
conn.Open();
var comm = conn.CreateCommand();
comm.CommandText = sql;
comm.Parameters.AddRange(para);
var reader = comm.ExecuteReader();
var result = new List<T>();
while (reader.Read())
{
var obj = new T();
obj.ConvertFrom(reader);
result.Add(obj);
}
return result;
}
}
  • 打赏
  • 举报
回复
简单看了一下博客的意思,我想许多人把读取DataReader成对象想象得太复杂了。这根本用不着反射,以及很多的switch判断,反射会让你的程序慢的不是一星半点(而是巨大),所以虽然你知道反射、研究反射,但是应该尽量做到几乎从来不使用反射

将DbDataReader转换为对象实体,我们定义一个接口就行了
public interface IConverterFromDbDataReader<T>
{
void Convert(DbDataReader reader, T obj);
}


而你的BLL内部的需要从DataReader读取出实体的对象就都可以实现这个接口,例如我随便举一个例子:
public class FileTransferBlock : IConverterFromDbDataReader<FileTransferBlock>
{
public long CallID;
public string SourceFile;
public string TargetFile;
public long StartPosition;

public void Convert(DbDataReader reader, FileTransferBlock obj)
{
obj.CallID = (long)reader["call_id"];
obj.SourceFile = (string)reader["source"];
obj.TargetFile = (string)reader["target"];
obj.StartPosition = (long)reader["position"];
}
}

这个例子清楚地说明了,如何将DataReader轻松地转换到对象的字段(或者属性)上。这并不增加多少工作量,因为你平常使用SqlHelper之类的来得到对象、或者从某种离散的一堆列值中得到对象时做的工作绝对不比这个更少。

剩下的SqlHelper中工作就非常清楚了,比如说它可能是这样写的
static public List<T> GetRecords<T>(string sql, params DbParameter[] para) where T : IConverterFromDbDataReader<T>, new()
{
using (DbConnection conn = CreateNewConnection())
{
conn.Open();
var comm = conn.CreateCommand();
comm.CommandText = sql;
comm.Parameters.AddRange(para);
var reader = comm.ExecuteReader();
var result = new List<T>();
while (reader.Read())
{
var obj = new T();
obj.Convert(reader, obj);
result.Add(obj);
}
return result;
}
}

那么我们直接调用 GetRecords<FileTransferBlock>(sqlString,null) 就能得到一个 FileTransferBlock 对象集合了。


上述,是因为这里讨论到比较底层的SqlHelper的写法。但是我的重点不单单是关于这个写法,我要强调的是:不要随便使用反射,而且大多数时候你也根本不需要使用反射!
generhappy 2011-09-26
  • 打赏
  • 举报
回复
总是使用dataset的多,呵呵
mvcmvcmvc2 2011-09-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 nxqcnxq 的回复:]

数据量大的时候datareader会有优势,小的时候看个人爱好了

不过你要是转换成实体类,个人觉的DataReader应该会好点,不然你用DataTable接受数据后,还要循环赋给实体
[/Quote]

多谢各位朋友了~~ 不过这个转换也是要循环付值的吧?
小珩 2011-09-26
  • 打赏
  • 举报
回复
数据量大的时候datareader会有优势,小的时候看个人爱好了

不过你要是转换成实体类,个人觉的DataReader应该会好点,不然你用DataTable接受数据后,还要循环赋给实体
yue547283947 2011-09-26
  • 打赏
  • 举报
回复
DataSet 和 datareader 都会用到 个人觉得速度不是很大区别。
datareader 要注意关闭

看个人爱好习惯吧。
subxli 2011-09-26
  • 打赏
  • 举报
回复
其实博客的文章也只是做为你的参考,并不能成为依据。

习惯使用dataset,数据多就用分页存储过程啦。
mvcmvcmvc2 2011-09-26
  • 打赏
  • 举报
回复
多谢楼上 再等等 上午结贴
linus2008117 2011-09-25
  • 打赏
  • 举报
回复
datareader
加载更多回复(11)

62,054

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧