DataReader etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
DataReader etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

21 Haziran 2016 Salı

DataReader

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.
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 metodu
Read ç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.
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ır
void 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);
  }
}
GetOrdinal
Verilen 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 İsmi
Sü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 metodu
Bu 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 metodu
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.
reader.NextResult();
DataReader ve Connection
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
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
Reader nesnemizin nasıl çalışacağını belirtir. Tek bir satır okumak istiyorsak SqlCommand'i şöyle kullanırız.
SqlDataReader reader = selectCommand.ExecuteReader(CommandBehavior.SingleRow);




26 Mayıs 2016 Perşembe

Streams.DataReader Sınıfı

Constructor metodu
Şöyle yaparız.
using (var dataReader = new Windows.Storage.Streams.DataReader(input.InputStream))
{
  ...
}
ByteOrder Alanı
Şöyle yaparız.
// use network order to read the packet
dataReader.ByteOrder = Windows.Storage.Streams.ByteOrder.BigEndian;
LoadAsync metodu
Şöyle yaparız. Belirtilen byte sayısı kadar verinin yüklenmesini bekler. Yükleme bitince Read metodları ile veri okunabilir.
//load the 2 byte command and 2 byte payload size into the buffer
await dataReader.LoadAsync(4);
ReadBytes metodu
Şöyle yaparız. Yüklenmiş tüm veriri okur.
byte[] data;
dataReader.ReadBytes(out data);
ReadUint16 metodu
Şöyle yaparız.
short payloadSize = dataReader.ReadUint16();