Я провел несколько сравнительных тестов с различными подходами:
public DataTable Read1(string query)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
var table = new DataTable();
using (var r = cmd.ExecuteReader())
table.Load(r);
return table;
}
}
public DataTable Read2<S>(string query) where S : IDbDataAdapter, IDisposable, new()
{
using (var da = new S())
{
using (da.SelectCommand = conn.CreateCommand())
{
da.SelectCommand.CommandText = query;
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0];
}
}
}
public IEnumerable<S> Read3<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
while (r.Read())
yield return selector(r);
}
}
public S[] Read4<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
return ((DbDataReader)r).Cast<IDataRecord>().Select(selector).ToArray();
}
}
public List<S> Read5<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
{
var items = new List<S>();
while (r.Read())
items.Add(selector(r));
return items;
}
}
}
1 и 2 возвращают DataTable
, в то время как остальные строго типизировали набор результатов, так что это точно не яблоки с яблоками, а я их время соответственно.
Только самое необходимое:
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Read1(query); // ~8900 - 9200ms
Read1(query).Rows.Cast<DataRow>().Select(selector).ToArray(); // ~9000 - 9400ms
Read2<MySqlDataAdapter>(query); // ~1750 - 2000ms
Read2<MySqlDataAdapter>(query).Rows.Cast<DataRow>().Select(selector).ToArray(); // ~1850 - 2000ms
Read3(query, selector).ToArray(); // ~1550 - 1750ms
Read4(query, selector); // ~1550 - 1700ms
Read5(query, selector); // ~1550 - 1650ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Запрос вернул около 1200 строк и 5 полей (выполнено 100 раз).Кроме Read1
все хорошо.Из всех я предпочитаю Read3
, который возвращает данные лениво, как перечислено.Это хорошо для памяти, если вам нужно только перечислить его.Чтобы иметь копию коллекции в памяти, лучше использовать Read4
или Read5
, если хотите.