Giriş
Tüm DataReader nesneleri IDataReader arayüzünden kalıtır. DataReader isimli soyut bir sınıf yoktur. SqlDataReader, OleDbDataReader (MS Access için), OracleDataReader, SQLiteDataReader en çok karşımıza çıkan sınıflar.
SQLiteDataReader System.Data.SQLite namespace içinde. Bu namespace için .Net ile gelmeyen DLL'leri projeye eklemek gerekiyor.
DataReader veritabanını aynı bir iterator gibi ileriye doğru dolaşmamızı sağlar. SQL gözlüğüyle bakarsak bir cursor gibidir. Select cümleleri ile çalışır.
Nasıl Elde Ederiz?
DbCommand nesnesinin ExecuteReader metodunu kullanırız.
Sütun yani alan sayısını şöyle alırız.
Reader'da satır olup olmadığını döner.
Read çağrısından sonra belirtilen sütunun null olup olmadığını döner. Şöyle yaparız.
Read Metodu
Sınıf şöyle kullanılır.
Tüm DataReader nesneleri IDataReader arayüzünden kalıtır. DataReader isimli soyut bir sınıf yoktur. SqlDataReader, OleDbDataReader (MS Access için), OracleDataReader, SQLiteDataReader en çok karşımıza çıkan sınıflar.
SQLiteDataReader System.Data.SQLite namespace içinde. Bu namespace için .Net ile gelmeyen DLL'leri projeye eklemek gerekiyor.
DataReader veritabanını aynı bir iterator gibi ileriye doğru dolaşmamızı sağlar. SQL gözlüğüyle bakarsak bir cursor gibidir. Select cümleleri ile çalışır.
Nasıl Elde Ederiz?
DbCommand nesnesinin ExecuteReader metodunu kullanırız.
SqlConnection connection = new SqlConnection(...);
SqlCommand selectCommand = new SqlCommand(selectStatement, connection);
connection.Open();
SqlDataReader reader = selectCommand.ExecuteReader();
FieldCount Alanı - Sütun SayısıSütun yani alan sayısını şöyle alırız.
reader.FieldCount;
HasRows - Alanı Reader'da satır olup olmadığını döner.
if (reader != null && reader.HasRows)
{
while (reader.Read())
{
...
}
}
IsDbNull metoduRead çağrısından sonra belirtilen sütunun null olup olmadığını döner. Şöyle yaparız.
if (!reader.IsDBNull(1)) {...}
Read Metodu
Sınıf şöyle kullanılır.
using(SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
var myString = rdr.GetString(0); //first column of the result.
}
}
Eğer sütun numaraları değil de sütun isimleri kullanılsın istiyorsak şöyle yapabiliriz.public Config(SqlDataReader sdr) {
for (int i = 0; i < sdr.FieldCount; i++) if (!sdr.IsDBNull(i)) {
switch (sdr.GetName(i)) {
case 'Id': Id = sdr.GetInt32(i); break;
...
}
}
}
yield yöntemi
Bazı kodlarda DataReader IEnumerable gibi kullanılıyor.
Verilen sütunu isminin sırasını döndürür.
Sütun numarasını bilmeden sadece isim ile erişebiliriz.
Şöyle yaparız.
Bu metod ile blob gibi alanlar stream gibi okunabilir.
Şöyle yaparız. G ile default formatlama yapılır.
Şöyle yaparız.
Sınıfın aynı zamanda Object dönen GetValue metodu da var. Bu metod weakly typed.
NextResult metodu
İki tane select cümlesi varsa, ikinic veri setine geçmemizi sağlar. Şöyle yaparız.
DataReader kapatılıncaya kadar connection açık tutulur. Connection başkasıyla paylaşılamaz.
Connection nesnesi mi using içinde mi kullanılmalı yoksa DataReader nesnesi mi using içinde mi kullanılmalı emin değilim.
MSDN örneklerinde connection using içinde kullanılıyor ve DataReader'ın Close() metodu çağrılmıyor.
DataReader ve Timeout
Eğer okunacak veri miktarı fazla ise DataReader Timeout hatası verebilir. Okumaya başlamadan önce Command nesnesinin timeout değerini ayarlamak gerekir. Mesela 3 dakika şöyle atanır
CommandBehavior Nedir
Reader nesnemizin nasıl çalışacağını belirtir. Tek bir satır okumak istiyorsak SqlCommand'i şöyle kullanırız.Bazı kodlarda DataReader IEnumerable gibi kullanılıyor.
IEnumerable<IDataRecord> GetRecords()
{
SqlConnection myConnection = new SqlConnection(@"...");
SqlCommand myCommand = new SqlCommand(@"...", myConnection);
myCommand.CommandType = System.Data.CommandType.Text;
myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
try
{
while (myReader.Read())
{
yield return myReader;
}
}
finally
{
myReader.Close();
}
}
Bu metod şöyle çağrılırvoid AnotherMethod()
{
foreach(var rec in GetRecords())
{
i++;
System.Console.WriteLine(rec.GetString(1));
if (i == 5)
break;
}
}
Bu yöntem veritabanına bağlantıyı tüm satırlar çekilinceye kadar açık tutar. Spring'deki gibi callback yöntemleri ile liste doldurmak veya bir başka metodu tetiklemek mümkün. Liste doldurmak için şöyle yaparız.IEnumerable<T> GetRecords<T>(Func<IDataRecord,T> extractor)
{
// ...
var result = new List<T>();
try
{
while (myReader.Read())
{
result.Add(extractor(myReader));
}
}
finally
{
myReader.Close();
}
return result;
}
Callback çağırmak için şöyle yaparız.void GetRecords(Action<IDataRecord> callback)
{
// ...
while (myReader.Read())
{
callback(myReader);
}
}
Benzer mantık C++ kodlarında da var.template<typename Action, typename ...Args>
void execute(Args... param, Action action)
{
// STUFF TO SET up connection.
// Start retrieving rows.
while(row = results->getNextRow())
{
call(action, row);
}
}
GetOrdinalVerilen sütunu isminin sırasını döndürür.
TimeSpan t = ((SqlDataReader)reader).GetTimeSpan(reader.GetOrdinal("MyColumn"));
Bracket Operator - Sütunlara Erişim İçin Sütun İsmiSütun numarasını bilmeden sadece isim ile erişebiliriz.
SQLiteDataReader reader = ...;
if (reader["expr1"] != DBNull.Value)
{
name= reader.GetString(0);
}
Bracket Operator - Sütunlara Erişim İçin Sütun NumarasıŞöyle yaparız.
string address = reader[1] as string;
GetBytes metoduBu metod ile blob gibi alanlar stream gibi okunabilir.
long bytesRead = sdr.GetBytes(0, readPosition, buffer, offset, count);
GetDecimal metoduŞöyle yaparız. G ile default formatlama yapılır.
var str = reader.GetDecimal(0).ToString("G");
GetTimeSpan metoduŞöyle yaparız.
TimeSpan myTimeSpan = ((SqlDataReader)reader).GetTimeSpan(0);
GetString metodu
Şöyle yaparız.reader.GetString(0);
GetValue metoduSınıfın aynı zamanda Object dönen GetValue metodu da var. Bu metod weakly typed.
NextResult metodu
İki tane select cümlesi varsa, ikinic veri setine geçmemizi sağlar. Şöyle yaparız.
reader.NextResult();
DataReader ve ConnectionDataReader kapatılıncaya kadar connection açık tutulur. Connection başkasıyla paylaşılamaz.
Connection nesnesi mi using içinde mi kullanılmalı yoksa DataReader nesnesi mi using içinde mi kullanılmalı emin değilim.
MSDN örneklerinde connection using içinde kullanılıyor ve DataReader'ın Close() metodu çağrılmıyor.
DataReader ve Timeout
Eğer okunacak veri miktarı fazla ise DataReader Timeout hatası verebilir. Okumaya başlamadan önce Command nesnesinin timeout değerini ayarlamak gerekir. Mesela 3 dakika şöyle atanır
using (SqlCommand command = new SqlCommand(q, connection))
{
command.CommandTimeout = 180;
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
dataList .Add(reader.GetString(0));
}
}
}
}
CommandBehavior Nedir
SqlDataReader reader = selectCommand.ExecuteReader(CommandBehavior.SingleRow);
Hiç yorum yok:
Yorum Gönder