哪个会更快。
1)循环数据头并创建基于填充数据表的自定义行和列
2)或创建一个dataAdapter对象,然后(填充)数据表。
在动态创建数据表时,数据加载器的性能是否仍然适用?
答案 0 :(得分:11)
假设您确实希望从数据库返回所有数据,那么在数据库和网络上花费的时间几乎肯定会使在进程中填充内存中的数据结构所花费的时间相形见绌。
是的,在某些情况下,您可能会通过使用DataReader获得少量保存 - 特别是如果您想要流式传输数据可能会有用 - 但如果您确实需要它,那么我会坚持使用最简单的代码。如果您认为DataSet群体导致严重的性能问题,请对其进行概要分析,然后然后尝试对其进行改进。
答案 1 :(得分:9)
DataAdapter在引擎盖下使用DataReader,因此您的体验可能会相同。
DataAdapter的好处是可以删除大量需要维护的代码。
这场辩论有点宗教问题,所以一定要四处寻找并决定什么最适合你的情况:
答案 2 :(得分:7)
您的选项#1会慢一些。但是,将数据加载器转换为数据表的方法比手动添加自定义行更好:
DataTable dt = new DataTable();
using (SqlConnection conn = GetOpenSqlConnection())
using (SqlCommand cmd = new SqlCommand("SQL Query here", conn)
using (IDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
我无法评论此与使用.Fill()
之间的区别。
答案 3 :(得分:3)
我不能说填充数据表本身,但使用datareader是最有效的读取方法。
答案 4 :(得分:2)
datareader更快。如果你使用2.0+,你可能甚至不必使用数据表。您可以使用对象的通用列表。
答案 5 :(得分:1)
当您需要示例显示加载数据的进度时,很高兴拥有DataReader。在DataSet中,您无法在加载数据的过程中执行某些操作。
另一方面,DataSet是一体化对象。所以DataSet要慢得多。 DataReader可以为代码中的数据操作非常慢的地方提供额外的提升。在这些位置将其从DataSet更改为DataReader。 DataReader在内存中占用的空间也更少。
当然,编写好的DataReader需要更多时间,但这是值得的。例如,当您使用从数据库中获取的图像或音乐时。
答案 6 :(得分:1)
与许多这样的问题一样,答案是:依赖。
如果您事先不知道数据的结构并且正在动态创建TableAdapter,那么动态DataTable将更有效。创建TableAdapter涉及大量代码生成。
但是,如果您事先知道数据的结构,那么问题就变成了,我需要多少功能?
如果您需要完整的CRUD实现,那么使用TableAdapter可以获得一些效率,而不是自己编写所有CRUD代码。此外,TableAdapter实现还可以(不是很好)。如果您需要更高效的东西,那么最好使用nHibernate或其他ORM。
如果您不需要完整的CRUD实现(即,这是一个只读解决方案)并且预先了解您的数据结构,那么您将必须测试TableAdapter只读实现的效率。动态生成的DataTable。如果我是一个博彩人,我会把钱花在TableAdapter实现上,因为你绑定了一次数据并多次读取它。
答案 7 :(得分:1)
前往DataReader
的{{1}}这是一种前向的,一行一行的方法,它按顺序读取数据,以便您在读取数据后立即获取记录连接时,将是最好的记忆和性能。
也就是说,在这两种方法之间,我发现Read
比IDataAdapter.Fill
快得多。当然这取决于实现..这是我发布的here:
DataTable.Load
第二种方法总是优于第一种方法。
public DataTable Read1<T>(string query) where T : IDbConnection, new()
{
using (var conn = new T())
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.ConnectionString = _connectionString;
cmd.Connection.Open();
var table = new DataTable();
table.Load(cmd.ExecuteReader());
return table;
}
}
}
public DataTable Read2<S, T>(string query) where S : IDbConnection, new()
where T : IDbDataAdapter, IDisposable, new()
{
using (var conn = new S())
{
using (var da = new T())
{
using (da.SelectCommand = conn.CreateCommand())
{
da.SelectCommand.CommandText = query;
da.SelectCommand.Connection.ConnectionString = _connectionString;
DataSet ds = new DataSet(); //conn is opened by dataadapter
da.Fill(ds);
return ds.Tables[0];
}
}
}
}
Stopwatch sw = Stopwatch.StartNew();
DataTable dt = null;
for (int i = 0; i < 100; i++)
{
dt = Read1<MySqlConnection>(query); // ~9800ms
dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms
dt = Read1<SQLiteConnection>(query); // ~4000ms
dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms
dt = Read1<SqlCeConnection>(query); // ~5700ms
dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms
dt = Read1<SqlConnection>(query); // ~850ms
dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms
dt = Read1<VistaDBConnection>(query); // ~3900ms
dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
在眼睛上看起来更好,但数据适配器表现更好(不要混淆一个db优于另一个,查询都不同)。两者之间的差异取决于查询。原因可能是Read1
要求在添加行(Load
上的方法时)逐行from the documentation检查各种约束,而DataTable
是在设计的DataAdapters上只为此 - 快速创建DataTables。