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

5 Kasım 2010

Smart Device' da SqlServerCe Database Erişimi - 3

Bu yazımızda Smart Device (Win-Ce) projelerimiz için SqlServerCe kütüphanesini kullanarak ele aldığımız Data Access sınıfımızı kullanmaya devam ediyoruz. Master-detail olarak hazırlayacağımız tablolarımıza, oluşturacağımız bir transaction ile aynı işlem içerisinde verileri kaydetmeye çalışacağız. (Buradaki işlemden kastımız oluşturacağımız bir button click event'ı dır.) Direk olarak bu makaleyi okumaya başlayan arkadaşlara önerim, öncelikle Smart Device' da SqlServerCe Database Erişimi - 1 ve Smart Device' da SqlServerCe Database Erişimi - 2 makalelerinde ele alınan konulara da göz gezdirmenizin faydalı olacağı kanısındayım.

El terminalimizin SqlServer Compact Edition db içerisinde Master-Detail olarak bulunan tablolar üzerinde veri kayıt etme, güncelleme veya silme gibi işlemlerde verilerin bütünlüğünü sağlamak, uygulamanın varlığını sürdürebilmesi açısından oldukça önemlidir diyebiliriz. Bu sebeple aynı event içerisinde gerçekleştirmek istediğimiz kayıt işlemimizi yaparken, hem transaction kullanmalı hem de veritabanı seviyesinde Foreign Key, Primary Key gibi tanımlamalarımızı da eksiksiz olarak yapmalıyız. Aşağıdaki örneklerde Primary, Foreign Key ve bunların kullanımları ile ilgili bir örnek geliştireceğiz.

Şimdi işe veritabanımızı ve tablolarımızı oluşturarak başlayalım. Burada dikkat etmemiz gereken ID int alanımızı Primary Key ve Identity(1,1) yani 1'den başlayarak otomatik 1 artan olarak tanımlıyoruz.


ID int primary key not null identity(1,1)


Alter Table SQL,

ALTER TABLE URUN

ADD CONSTRAINT FK_URUN_URUN_GRUP

FOREIGN KEY (URUN_GRUP_ID) REFERENCES URUN_GRUP(ID)


Örneğimizde master-detail olarak URUN_GRUP ve URUN tablolarını oluşturacağız. CreateDb() methodumuzu aşağıdaki gibi hazırlıyoruz.

public static void CreateDb() {

Cursor.Current = Cursors.WaitCursor;

SqlCeConnection conn_Db = null;

SqlCeCommand cmd = null;

try {

var engine = new SqlCeEngine("Data Source =" + dbPath + ";password='1234567'");

engine.CreateDatabase();

engine.Dispose();


conn_Db = new SqlCeConnection("Data Source =" + dbPath + ";password='1234567'");


conn_Db.Open();

cmd = conn_Db.CreateCommand();
cmd.CommandText = " CREATE TABLE URUN_GRUP\n" +

" (\n" +

" ID int primary key not null identity(1,1),\n" +

" ADI nvarchar(25) not null\n" +

" )";

cmd.ExecuteNonQuery();


cmd.CommandText = " CREATE TABLE URUN\n" +

" (\n" +

" ID int primary key not null identity(1,1),\n" +

" URUN_GRUP_ID int not null, \n" +

" ADI nvarchar(50) \n" +

" ) ";

cmd.ExecuteNonQuery();


cmd.CommandText = " ALTER TABLE URUN\n" +

" ADD CONSTRAINT FK_URUN_URUN_GRUP\n" +

" FOREIGN KEY (URUN_GRUP_ID) REFERENCES URUN_GRUP(ID)";

cmd.ExecuteNonQuery();

cmd.Dispose();

MessageBox.Show("Veritabanı Oluşturuldu.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);

}


catch (SqlCeException ex) {

if (cmd != null) {

cmd.Dispose();

}

ShowErrors(ex);

}

catch (Exception) {

throw;

}

finally {

Cursor.Current = Cursors.Default;

}

}



Yukarıdaki kod satırlarında dikkat edecek olursak ALTER TABLE ile URUN tablomuzun URUN_GRUP_ID alanını Foreign Key olarak tanımladık. Şimdi de oluşturduğumuz tablolara aynı event içerisinde kayıt satırları ekleyelim.


private void btnKaydet_Click(object sender, EventArgs e) {

try {


// Transaction başlatılıyor.

SqlCompactDatabase.BeginTransaction();

// Master tabloya kayıt atılıyor.

const string sqlGrup = " insert into URUN_GRUP (ADI) values(@p1) ";

MyCeParameter pGrupAdi = new MyCeParameter("@p1", "Bilgisayar",ParameterDirection.Input);


SqlCompactDatabase.ExecuteNonQuery(sqlGrup, pGrupAdi);


// Master tabloya kaydedilen Identity ID değeri elde ediliyor.

int grup_id = Convert.ToInt32(SqlCompactDatabase.ExecuteScalerText("select @@identity", null));


// Detay tabloya kayıtlar ekleniyor. Master tablodan elde edilen Grup_Id alanı da set ediliyor.

foreach (var urun in new string[] { "İşlemci", "Ana Kart", "Sabit Disk", "Solid State Disk" } ) {

string sqlUrun = " insert into URUN (URUN_GRUP_ID,ADI) values(@p1,@p2) ";

MyCeParameter pGrupId = new MyCeParameter("@p1", grup_id);

MyCeParameter pAdi = new MyCeParameter("@p2", urun);

SqlCompactDatabase.ExecuteNonQuery(sqlUrun, pGrupId, pAdi);

}


// Transaction Commit edilerek işlem tamamlanıyor.

SqlCompactDatabase.CommitTransaction();

}


catch (Exception ex) {

SqlCompactDatabase.RollBackTransaction();

MessageBox.Show(ex.Message);

}

}


Yukarıdaki C# kod satırlarında görüleceği üzere, master URUN_GRUP tablosuna kayıt ekledikten sonra bu tablonun identity ID alanı değerini @@identity ile elde etmiş olduk. select @@Identity bize tabloya en son kayıt edilen identity alanın değerini dönecektir. Elde ettiğimiz ID alanını URUN_GRUP_ID olarak, detail URUN tablosunda kullandık. URUN_GRUP_ID alanı Foreign Key tanımlandığından kayıt sırasında bir sıkıntı yaşamadık. Grup Id'si tanımlanmamış bir kayıt satırını kaydetmemiz mümkün olmayacaktı. Aksi durumda (Foreign Key bozulması
durumlarında) aşağıdaki gibi bir hata ile karşılaşılır. (A foreign key value cannot be inserted because a corresponding primary key value does not exist.)


Ayrıca şunu da belirtmeliyiz, Compact FrameworkSqlCeParameter.Direction Property her zaman için Input parametre döndürmektedir. Eğer farklı bir parameter direction verilirse InvalidOperationException hatası fırlatılacaktır.

Eğer output parametre kullanabilir olsaydık, select @@identity kullanmadan da ID değerini insert komut satırı içinde output parametre olarak döndürerek de elde etme şansımız olurdu.

Kolay gelsin.

3 Kasım 2010

Smart Device' da SqlCe Database Erişimi - 2

Merhabalar, bu yazımızda Smart Device' da SqlCe Database Erişimi - 1 başlıklı makalemizin devamı olan, veri erişim katmanı (Ado.Net/Data Access) olarak oluşturduğumuz sınıfımızı transaction kullanımı ile detaylandıracağız. Önceki makelemizde SqlCeConnection isimli sınıfımıza ExecuteNonQuery, ExecuteScalerText, GetDataTable methodlarını eklemiştik. Bu makelemizde ise bu sınıfımız içerisine SqlCeTransaction nesnesini de ekleyerek örneklerle detaylandıracağız.

Öncelikle SqlCeTransaction nesnesini kullanacağımız public methodları (begin, commit, rollback) static sınıfımıza ekleyelim, sınıfımızın son durumunu class diagram üzerinde görelim.



Şimdi, Sırasıyla BeginTransaction, CommitTransaction ve RollBackTransaction methodlarımızı da sırasıyla ekleyelim. Static sınıfımızın dışından diğer public method'larımıza erişir gibi transaction'ımızı da yönetebilir olacağız.

Static sınıfımıza 'trans' adında static SqlCeTransaction değişkenimizi ekleyerek düzenlemeye
başlayalım.


private static SqlCeTransaction trans;
private static SqlCeConnection conn;
Begin Transaction
public static void BeginTransaction() {

try {

if (conn != null) {

trans = conn.BeginTransaction();

}

}

catch (Exception) {

throw;

}

}


Commit Transaction
public static void CommitTransaction() {

try {

if (trans != null) {

trans.Commit();

trans.Dispose();

trans = null;

}

}

catch (Exception) {

throw;

}

}


RollBack Transaction
public static void RollBackTransaction() {

try {

if (trans != null) {

trans.Rollback();

trans.Dispose();

trans = null;

}

}

catch (Exception) {

throw;

}

}


Dikkat edileceği üzere transaction yönetim methodlarımızı public olarak, dışarıdan erişilebilecek şekilde yazdık. Bir transaction nesnesi oluşturup, başlattıktan sonra ExecuteNonQuery gibi methodlarımızın SqlCeCommand nesnesinin bu transaction nesnesinden etkilenmesini sağlamamız gerekmektedir. Bunun için aşağıdaki gibi ExecuteNonQuery ve ExecuteScalerText isimli methodlarımızda da düzenleme yapıyoruz.

public static int ExecuteNonQuery(string sql, params MyCeParameter[] parameters) {

var rowsAffected = 0;

try {

using (var cmd = new SqlCeCommand()) {

cmd.Connection = conn;

cmd.CommandText = sql;

if (parameters != null && parameters.Length != 0) {

bindParametersToSqlCe(parameters, cmd);

}

//Transaction null değil ise (BeginTransaction methodu ile başlatılmış)

//command nesnesinin Transaction property'si set edilir.

if (trans != null) {

cmd.Transaction = trans;

}

rowsAffected = cmd.ExecuteNonQuery();

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

return rowsAffected;

}


public static object ExecuteScalerText(string sql, MyCeParameter[] parameters) {

object result = null;

try {

using (SqlCeCommand cmd = new SqlCeCommand()) {

cmd.Connection = conn;

cmd.CommandText = sql;

if (parameters != null && parameters.Length != 0) {

bindParametersToSqlCe(parameters, cmd);

}


//Transaction null değil ise (BeginTransaction methodu ile başlatılmış)

//command nesnesinin Transaction property'si set edilir.

if (trans != null) {

cmd.Transaction = trans;

}

result = cmd.ExecuteScalar();}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

catch (Exception ex) {

ShowPdaMessage.ShowException(ex);

}

return result;

}


Sınıfımıza Transaction methodları da eklendiğine göre, bir örnek ile kullanabiliriz.
private void urunKaydet() {

try {


// Transaction başlatılıyor..

SqlCompactDatabase.BeginTransaction();

const string sql = "insert into URUN(KODU,ADI) values(@p1,@p2) ";

MyCeParameter kodu = new MyCeParameter("@p1", 1, ParameterDirection.Input);

MyCeParameter adi = new MyCeParameter("@p2", "Vida", ParameterDirection.Input);

SqlCompactDatabase.ExecuteNonQuery(sql, kodu,adi);


const string sqlDetail = "insert into URUN_DETAY(URUN_KODU,DETAY,RENK) values(@p1,@p2,@p3) ";

MyCeParameter urun_kodu = new MyCeParameter("@p1", 1, ParameterDirection.Input);

MyCeParameter detay_bilgi = new MyCeParameter("@p2", "3 mm", ParameterDirection.Input);

MyCeParameter renk = new MyCeParameter("@p3", "Siyah", ParameterDirection.Input);

SqlCompactDatabase.ExecuteNonQuery(sqlDetail, urun_kodu, detay_bilgi, renk );

//Transaction Commit ediliyor.

SqlCompactDatabase.CommitTransaction();

}

catch (Exception) {

//Eğer hata oluşur ve transaction başlatılmış ise geri alınır.

SqlCompactDatabase.RollBackTransaction();

throw;

}

}

Buradaki örnekte de görüldüğü gibi dilediğimiz zaman transaction başlatıp, sonlandırabilir, ya da iş mantığına göre dilediğimiz yerde eğer bir transaction başlatılmışsa rollback ile yapılan işlemleri geri alabiliriz. Kolay gelsin.

Smart Device' da SqlServerCe Database Erişimi - 1

Merhaba, Microsoft her ne kadar Windows Phone 7 ile VS 2010'da smart device project seçeneğini kaldırmış olsa dahi, endüstriyel çalışma ortamları için geliştirilen uygulamaların çoğalması ile daha uzunca bir süre Visual Studio 2008 'de SmartDevice projeleri ile uygulama geliştirileceğini düşünüyorum. Bu vesile ile bu makalemizde yoğun olarak ihtiyaç duyduğumuz bir smart device projesinde kullanılan SqlServerCe veritabanımıza erişim için örnek bir data access class (veri erişim sınıfı) hazırlayacağız.

Pda uygulamamızın her hangi bir sınıfı içinden veritabanımıza erişmek, veri kaydetmek, silmek gibi işlemlere ihtiyaç duyulmaktadır. Tüm bu işlemlerimiz için her defasında SqlCeCommand, SqlCeDataAdapter, SqlCeParameter gibi nesnelerin tekrar tekrar oluşturulması hem daha fazla satır kod yazmamıza hem de bellek güçleri zaten belirli bir seviyede olan pda'ler için bir dezavantaj sağlayacaktır.

Bir Pda içinde çalışan uygulamamızdan veritabanına erişim gerçekleştirirken çağrılarımızın senkron yapıldığını ve çoğunlukla aynı anda db'ye bir kullanıcının erişim isteğinde bulunduğunu göz önünde bulundurursak static method'lardan da faydalanarak örnek sınıfımızı geliştirmeye başlayabiliriz.

Sınıfımızı static olarak SqlCompactDatabase isminde tanımlayacağız.

public static class SqlCompactDatabase



Static sınıfımıza ait constractor'ümüzü de static tanımlayacağız. Böylece yalnızca bir kez, uygulama ayağa kalktığında (çalışmaya başladığında) constractor içindeki kodlar çalışacaktır. Uygulamamızdan veri tabanına erişirken sürekli olarak SqlCeParameter nesnesi oluşturmamak için öncelikle kendimize ait bir parametre nesnesi oluşturalım ve bu parameter nesnesi ile SqlCeParameter karşılıklarını burada tanımlayabiliriz.

Ayrıca, SqlCeParameter ile tek tek bir parametremizin tipini, string ise uzunluğunu girmek fazla sayıda parametre gerektiren işlemlerimizde oldukça zaman kaybedici olacaktır bunun yerine kullanacağımız MyCeParameter isimli sınıfımızı aşağıdaki gibi tanımlayalım.

C#

public class MyCeParameter {


public MyCeParameter(string name,object value,ParameterDirection direction) {

Value = value;

Name = name;

Direction = direction;


if
(value == null) {

Value = DBNull.Value;

return;

}

Type = value.GetType();


if (Type == typeof(string)) {

Size = ((string)value).Length;

}



else if (Type == typeof(byte[]))
{

Size = ((byte[])value).Length;

}

else {

Size = 0;

}

}

public Type Type { get; set; }

public int Size { get;set; }

public object Value { get; set; }

public string Name { get; set; }

public ParameterDirection Direction { get; set; }

}



Şimdi de SqlCompactDatabase sınıfımıza ait static constractor' ümüzü yazalım. MyCeParameter oluşturuken ctor'da parametre olarak vereceğimiz tip için Type kullanıyoruz. C# Type'lara karşılık gelen SqlDbType'larımızı bir dictionary'ye ekleyebiliriz.

C#


private static readonly Dictionary<Type, SqlDbType> DictTypeToSql;

static SqlCompactDatabase() {

DictTypeToSql = new Dictionary<Type, SqlDbType>();

DictTypeToSql.Add(typeof(Byte[]), SqlDbType.Image);

DictTypeToSql.Add(typeof(String), SqlDbType.NVarChar);

DictTypeToSql.Add(typeof(Char), SqlDbType.Char);

DictTypeToSql.Add(typeof(DateTime), SqlDbType.DateTime);

DictTypeToSql.Add(typeof(Double), SqlDbType.Float);

DictTypeToSql.Add(typeof(Decimal), SqlDbType.Decimal);

DictTypeToSql.Add(typeof(Int16), SqlDbType.SmallInt);

DictTypeToSql.Add(typeof(Int32), SqlDbType.Int);

DictTypeToSql.Add(typeof(Int64), SqlDbType.BigInt);

}



SqlCompactDatabase sınıfımıza ait olacak SqlCeConnection nesnemizi de static constractor de oluşturabiliriz. Connection nesnemizi oluşturmak için uygulamamızın bağlanacağı veritabanı dosya yolunu da constractör içinde elde ediyoruz. Constractor'ümüzün ve private değişkenkerimizin son hali aşağıdaki gibi olsun.

C#


private static SqlCeConnection conn;

private static readonly Dictionary<Type, SqlDbType> DictTypeToSql;

//Static Contractor

static SqlCompactDatabase() {

string currentDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); dbPath = string.Concat(currentDirectory, "\\urundb.sdf");

if (conn == null) {

conn = new SqlCeConnection("Data Source =" + dbPath + ";password='1234567'");

}


DictTypeToSql = new Dictionary<Type, SqlDbType>();

DictTypeToSql.Add(typeof(Byte[]), SqlDbType.Image);

DictTypeToSql.Add(typeof(String), SqlDbType.NVarChar);

DictTypeToSql.Add(typeof(Char), SqlDbType.Char);

DictTypeToSql.Add(typeof(DateTime), SqlDbType.DateTime);

DictTypeToSql.Add(typeof(Double), SqlDbType.Float);

DictTypeToSql.Add(typeof(Decimal), SqlDbType.Decimal);

DictTypeToSql.Add(typeof(Int16), SqlDbType.SmallInt);

DictTypeToSql.Add(typeof(Int32), SqlDbType.Int);

DictTypeToSql.Add(typeof(Int64), SqlDbType.BigInt);

}



Şimde de SqlCompactDatabase sınıfımızın public ve private olarak kullanılacak methodlarını tanımlayalım. Tabii public ile uygulamamızın herhangi bir yerinden yapacağımız Insert, Updata, Delete ve Select işlemlerini yapabileceğimiz methodlar olacak. Private methodlarımız içinde ise

SqlCompactDatabase sınıfımız içinde gerekli olacak methodlarımızı yazacağız. private ve public olarak tanımlanacak method isimlerimizi de aşağıdaki gibi yazalım.


public static void OpenDb()Uygulamamız ilk ayağa kalkarken
db connection açmak için kullanacığız. Aynı anda bir kullanıcı db
üzerinde erişim yapacağı için bir defa açmamız yeterli olacak.
public static void CloseDb()Uygulamamızı kapanırken db connection'ımızı
kapatmak için kullanacağız.
public static void CreateDb()Local SqlCe db oluşturmak için kullanacağız.
public static void ShowErrors(SqlCeException e)Oluşabilecek SqlCeException'ları detaylı
görebilmek için kullanacağız.
public static int ExecuteNonQuery(string sql,
params MyCeParameter[] parameters)
Insert, Update ve Delete Sql Query'lerimizi
çalıştırmak için kullanacağız. Sql string query'mizi ve var ise
sırasıyla parametrelerimizi ekleyeceğiz.
public static
object ExecuteScalerText(string sql, MyCeParameter[] parameters)
Geriye yalnızca bir object dönen sorgular
için kullanacağız.
public static
DataTable GetDataTable(string sql, params MyCeParameter[] parameters)
Geriye DataTable nesnesi dönmesi gereken
sorgularda kullanacağız.
private static
void bindParametersToSqlCe(MyCeParameter[] parameters, SqlCeCommand cmd)
MyCeParameter nesnesi olarak verdiğimiz
parametreyi SqlCeParameter nesnesi olarak SqlCeCommand nesnesine bind
etmek için kullanacağız.
private static
SqlDbType getSqlCeDbType(Type type)
C# Type olarak verdiğimiz tipin SqlDbType
karşılığını elde etmek için kullanacağız.
Aşağıdaki kod satırlarında görüleceği üzere, dispose edilebilir nesneler için kullanılan using bloğu içinde SqlCeCommand oluşturacağız. Ve eğer var ise parametrelerimizi de SqlCeCommand nesnemize ekledikten sonra sorgumuzu çalıştırıyoruz ve dönüş değeri olarak kaç satırın etkilendiğini görebileceğiz.


public static int ExecuteNonQuery(string sql, params MyCeParameter[] parameters) {

var rowsAffected = 0;

try {

using (var cmd = new SqlCeCommand()) {

cmd.Connection = conn;

cmd.CommandText = sql;

if (parameters != null) {

bindParametersToSqlCe(parameters, cmd);

}

rowsAffected = cmd.ExecuteNonQuery();

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

return rowsAffected;

}



Yukarıdaki method içinde parametrelerimizi SqlCeCommand nesnesine bind etmek için bindParametersToSqlCe private methodunu kullandık.


private static void bindParametersToSqlCe(MyCeParameter[] parameters, SqlCeCommand cmd) {


try {


for (var i = 0; i < parameters.Length; i++) {

MyCeParameter myParam = parameters[i];

SqlCeParameter p = new SqlCeParameter(myParam.Name, getSqlCeDbType(myParam.Type), myParam.Size);

p.Value = myParam.Value;

p.Direction = myParam.Direction;

cmd.Parameters.Add(p);

}

}

catch (Exception) {

throw;

}

}





private static SqlDbType getSqlCeDbType(Type type) {


return DictTypeToSql[type];


}


Benzer şekilde veri erişim sınıfımızın diğer methodlarını da aşağıdaki gibi oluşturabiliriz. Bu sınıfımızın son halini aşağıdaki gibi yazalım.

C#


public static class SqlCompactDatabase {


private static string dbPath;

private static SqlCeConnection conn;

private static readonly Dictionary<Type, SqlDbType> DictTypeToSql;

static SqlCompactDatabase() {

string currentDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);


dbPath = string.Concat(currentDirectory, "\\urundb");

if (conn == null) {

conn = new SqlCeConnection("Data Source =" + dbPath + ";password='1234567'");

}

DictTypeToSql = new Dictionary<Type, SqlDbType>();

DictTypeToSql.Add(typeof(Byte[]), SqlDbType.Image);

DictTypeToSql.Add(typeof(String), SqlDbType.NVarChar);

DictTypeToSql.Add(typeof(Char), SqlDbType.Char);

DictTypeToSql.Add(typeof(DateTime), SqlDbType.DateTime);

DictTypeToSql.Add(typeof(Double), SqlDbType.Float);

DictTypeToSql.Add(typeof(Decimal), SqlDbType.Decimal);

DictTypeToSql.Add(typeof(Int16), SqlDbType.SmallInt);

DictTypeToSql.Add(typeof(Int32), SqlDbType.Int);

DictTypeToSql.Add(typeof(Int64), SqlDbType.BigInt);

}


public static void OpenDb() {

try {


if (conn == null) {

conn = new SqlCeConnection("Data Source =" + dbPath + ";password='1234567'");

}

if (conn.State == ConnectionState.Closed) {

tryConnection:

try {

conn.Open();

}

catch (SqlCeException ex) {

if (ex.NativeError == 25138) {

var sce = new SqlCeEngine(conn.ConnectionString);

sce.Upgrade();

goto tryConnection;

}

}

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

catch (Exception) {

throw;

}

}

public static void CloseDb() {

try {

if (conn != null && conn.State == ConnectionState.Open) {

conn.Close();

conn.Dispose();

conn = null;

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

catch (Exception) {

throw;

}

}



public static void ShowErrors(SqlCeException e) {

SqlCeErrorCollection errorCollection = e.Errors;

StringBuilder bld = new StringBuilder();

Exception inner = e.InnerException;

if (null != inner) {

MessageBox.Show("Inner Exception: " + inner.ToString());

}

foreach (SqlCeError err in errorCollection) {

bld.Append("\n Error Code: " + err.HResult.ToString("X"));

bld.Append("\n Message : " + err.Message);

bld.Append("\n Minor Err.: " + err.NativeError);

bld.Append("\n Source : " + err.Source);

foreach (int numPar in err.NumericErrorParameters) {

if (0 != numPar)

bld.Append("\n Num. Par. : " + numPar);

}


foreach (string errPar in err.ErrorParameters) {

if (String.Empty != errPar)

bld.Append("\n Err. Par. : " + errPar);

}

MessageBox.Show(bld.ToString());

bld.Remove(0, bld.Length);

}


}



public static int ExecuteNonQuery(string sql, params MyCeParameter[] parameters) {

var rowsAffected = 0;

try {


using (var cmd = new SqlCeCommand()) {

cmd.Connection = conn;

cmd.CommandText = sql;

if (parameters != null && parameters.Length != 0) {

bindParametersToSqlCe(parameters, cmd);

}

rowsAffected = cmd.ExecuteNonQuery();

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}

return rowsAffected;

}

private static void bindParametersToSqlCe(MyCeParameter[] parameters, SqlCeCommand

cmd) {


try {

for (var i = 0; i < parameters.Length; i++) {

MyCeParameter myParam = parameters[i];

SqlCeParameter p = new SqlCeParameter(myParam.Name, getSqlCeDbType(myParam.Type), myParam.Size);

p.Value = myParam.Value;

p.Direction = myParam.Direction;

cmd.Parameters.Add(p);

}

}

catch (Exception) {

throw;

}

}


private static SqlDbType getSqlCeDbType(Type type) {

return DictTypeToSql[type];

}


public static object ExecuteScalerText(string sql, MyCeParameter[] parameters) {

object result = null;

try {

using (SqlCeCommand cmd = new SqlCeCommand()) {

cmd.Connection = conn;

cmd.CommandText = sql;

if (parameters != null) {

bindParametersToSqlCe(parameters, cmd);

}

result = cmd.ExecuteScalar();

}

}

catch (SqlCeException ex) {

ShowErrors(ex);

}


catch (Exception) {

throw;

}


return result;

}

public static DataTable GetDataTable(string sql, params MyCeParameter[] parameters) {

DataTable dt = new DataTable();

try {

using (SqlCeCommand cmd = new SqlCeCommand(sql)) {

cmd.Connection = conn;

if (parameters != null) {

bindParametersToSqlCe(parameters, cmd);

}

using (SqlCeDataAdapter da = new SqlCeDataAdapter(cmd)) {

dt = new DataTable();

da.Fill(dt);

}

}

if (dt.Rows.Count == 0) {

return null;

}

return dt;

}

catch (SqlCeException ex) {

ShowErrors(ex);

return null;

}

finally {

if (dt != null) {

dt.Dispose();

}

}

}




public static void CreateDb() {


Cursor.Current = Cursors.WaitCursor;

SqlCeConnection conn_Db = null;

SqlCeCommand cmd = null;

try {

var engine = new SqlCeEngine("Data Source =" + dbPath + ";password='1234567'");

engine.CreateDatabase();

engine.Dispose();


conn_Db = new SqlCeConnection("Data Source =" + dbPath + ";password='1234567'");

conn_Db.Open();

cmd = conn_Db.CreateCommand();

cmd.CommandText = "CREATE TABLE URUN\n" +

"(\n" +


"KODU int not null primary key,\n" +


"ADI nvarchar(25)\n" +


")";


cmd.ExecuteNonQuery();

cmd.Dispose();

MessageBox.Show("Veritabanı Oluşturuldu.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);

}

catch (SqlCeException ex) {

if (cmd != null) {

cmd.Dispose();

}

ShowErrors(ex);

}

catch (Exception) {

throw;

}


finally {

Cursor.Current = Cursors.Default;

}

}

}



Sınıfımızı tamamladıktan sonra veri tabanımız için oluşturduğumuz (CreateDb methodu ile) Urun isimli tablomuza bir ürün satırı ekleme örneği yaparak yazımızı tamamlayalım.

C#

private void urunKaydet() {

try {

const string sql = "insert into URUN(KODU,ADI) values(@p1,@p2) ";

MyCeParameter kodu = new MyCeParameter("@p1", 1, ParameterDirection.Input);

MyCeParameter adi = new MyCeParameter("@p2", "Vida", ParameterDirection.Input);

SqlCompactDatabase.ExecuteNonQuery(sql, kodu,adi);

}

catch (Exception) {

throw;

}

}

Yukarıdaki örnekte görüldüğü gibi parametrelerimi oluştururken MyCeParameter nesnemi kullanarak ayrıca parametre hakkındaki detayları belirtmeme gerek kalmıyor, SqlCeCommand,
SqlCeDataAdapter nesnelerim ise yalnızca SqlCompactDatabase static sınıfım içinde oluşturulup dispose ediliyor veya aşağıdaki örnekte olduğu gibi datagrid'imin datasourse'una rahatça Urun'lerimi bind edebiliyorum.

C#


private void urunleriListele() {


try {


dataGridUrunler.DataSource = SqlCompactDatabase.GetDataTable("select * from URUN", null);


}


catch (Exception) {


throw;


}


}


Dilerim faydalı bir yazı olmuştur. Bir sonraki yazımızda oluşturduğumuz SqlCompactDatabase sınıfımıza SqlCeTransaction nesnesi de ekleyerek sınıfımızı daha detaylı hale getirmeye çalışacağız. Kolay gelsin.