27 Ocak 2017 Cuma

SQL ile C# 'a kod oluşturma -2 (Tembellik SQL'i )


Merhaba,

Diyelim ki;
Veritabanımdaki tüm tablolarımda aşağıdaki anlamda alanlarım var.


* durum ( 0 ise pasif, 1 ise aktif, 2 aktif ama görülmez,listelenmez, 3 ise silindi olacak.. )
* oluşturma zamanı
* oluşturan kullanıcı
* güncelleme zamanı
* güncelleyen kullanıcı
* silme zamanı
* silen kullanıcı


Projemde LINQ kullanıyorum ve bu alanları eklemek kodda ilerledikten sonradan aklıma geldi.
Tüm LINQ CRUD methodlarını bulup bu alanları eklemek zahmetli olacağından, LINQ Datacontext classına
aşağıdaki gibi insert, update, delete override methodlarını yazarak bu işi halledeceğiz...

Ancak burada da tembellik damarı bastırdı, tüm tablolar için bunları tekrar kopyala ismini değiştir kim uğraşacak en iyisi
SQL veya Excel kullanarak tablo isimlerine göre bu kodu çoklamak.
Burada ben T-SQL cursor kullanarak yukardaki alanların geçtiği tüm tablo isimlerine göre bu kod bloğunu çoklattım.


SQL Management studio'da sonucu grid olarak gösterirsek satır sonu ifadeleri çalışmıyor tüm kod tek satır halinde oluşuyor.
Text kısmında göster dersek sonuç olarak ortaya çıkan metin uzun olduğundan burada anlamsız bir şekikde eksik gözüküyor.
O yüzden sql'i run etmeden önce File (Dosyada görüntüle) yi seçeceğiz..

Çoklamak istediğimiz kod bloğu (sadece bir tablo için ) şu şekilde :


partial class DatabaseContext
{

#region "TABLO_ABC"

partial void UpdateTABLO_ABC(TABLO_ABC instance)
{

instance.DATE_UPDATED = System.DateTime.Now;
instance.USER_UPDATED = Global.Instance.UserId;
this.ExecuteDynamicUpdate(instance);
}

partial void InsertTABLO_ABC(TABLO_ABC instance)
{
instance.DATE_CREATED = System.DateTime.Now;
instance.USER_CREATED = Global.Instance.UserId;
instance.STATUS = 1; // yeni eklenen kayıtlarda durumu 1 yapıyoruz...
this.ExecuteDynamicInsert(instance);
}

partial void DeleteTABLO_ABC(TABLO_ABC instance)
{
instance.DATE_DELETED = System.DateTime.Now;
instance.USER_DELETED = Global.Instance.UserId;
instance.STATUS = 3; //silme işlemi gerçekleştirilmek istenince durum=3 yapıp biz update yönlendiriyoruz.
//ekranda sadece durum=1 ler geldiğinden kullanıcı bu satırı görmüyor..
this.ExecuteDynamicUpdate(instance);
}

#endregion

}



Bu override methodlarımızı, LINQ'te veritabanı şemasını oluşturduğumuzda ekrana ayrı tabda açılan .cs uzantılı boş override DatabaseContext class'ına yazacağız. Daha sonraki veritabanı şema düzenlemeleri bu dosyadaki eklenti-override metodlarımızı silmiyor..

Bizim tüm tablolar için çoklamak istediğimiz kısım #region #endregion kısmı

Burda dinamik olarak bu metni tüm tablolar için güncellemek için sadece yapmamız gereken tablo isimlerini depiştirmek. Çünkü diğer kodların
hepsi tüm tablolar için aynı olacak. Bu yüzden T-SQL de, bu kod bloğunu tablo isimlerinin yerine yazarak nvarchar(MAX) tipinde
@SQL değişkenine atıyoruz.

Sonra içinde yukarıdaki sütunlardan birisi geçen tüm tablolarımızın isimlerini declare cursor ile select ediyoruz.
Her cursor döngüsünde bu @SQL değişkenindeki ifadesini cursor'ün sıradaki satırındaki tablo ismi ifadesi ile değiştirip sonucu
nvarchar(MAX) tipindeki @tmp değişkenine atıyoruz.
Sonrada bu değeri print ile dosyaya yazdırıyoruz...

Oluşan dosyayı .txt uzantısı ile kaydederseniz içeriğini kopyalayıp .cs dosyasına yapıştırabilirsiniz.

Yardımcı T-SQL bloğumuz..... :



/* çalıştırmadan önce sonucun dosyada gösterilmesi için yukarıdan Result to File (CTRL + SHIFT + F) seçiniz.. */

-- bazı tabloları istisna ederek içinde USER_DELETED sütunu geçen tüm tabloları cursor'e select ediyoruz..
declare c Cursor for select name
from sys.tables t where type='U'
and exists(select column_id from sys.columns where object_id=OBJECT_ID(t.name,'U')
and name='USER_DELETED')
and t.name not in ('_tmp','sysdiagrams','ISTISNA_TABLO','PARAM_TABLO')

open c

-- değişken tanımları
declare @newLine AS CHAR(2) = CHAR(13) + CHAR(10)
declare @table nvarchar(30)
declare @SQL nvarchar(MAX)
declare @tmp nvarchar(MAX)

-- başına ve sonuna ' koyarak tablo ismi olarak değiştirilmiş kod bloğumuzu @SQL değişkenine atıyoruz..
set @SQL='
#region ""

partial void Update( instance)
{

instance.DATE_UPDATED = System.DateTime.Now;
instance.USER_UPDATED = Global.Instance.UserId;
this.ExecuteDynamicUpdate(instance);
}

partial void Insert( instance)
{
instance.DATE_CREATED = System.DateTime.Now;
instance.USER_CREATED = Global.Instance.UserId;
instance.STATUS = 1; // yeni eklenen kayıtlarda durumu 1 yapıyoruz...
this.ExecuteDynamicInsert(instance);
}

partial void Delete( instance)
{
instance.DATE_DELETED = System.DateTime.Now;
instance.USER_DELETED = Global.Instance.UserId;
instance.STATUS = 3; //silme işlemi gerçekleştirilmek istenince durum=3 yapıp biz update yönlendiriyoruz.
//ekranda sadece durum=1 ler geldiğinden kullanıcı bu satırı görmüyor..
this.ExecuteDynamicUpdate(instance);
}

#endregion

}

'
-- ile tablo ismini al..
fetch from c into @table
while @@FETCH_STATUS!=-1
begin
-- ifadelerini cursorün sıradaki tablo ismi ile değiştir..
set @tmp=REPLACE(@SQL,'',@table)

-- sonucu dosyaya yazdır
print @tmp

--gerekmeyebilir.. bir satırsonu eklemek içi
print @newLine

-- cursor'ü ilerlet... >>>
fetch from c into @table
end


-- kapat yoket...
close c
deallocate c

/*
sql'i çalıştırınca ekrana gelen kaydet kısmında dosya tipi tüm dosyalar dosya ismi sonuc.txt yapabilirsiniz..
dosya içeriğini alıp .cs dosyanıza yapıştırın..
*/




13 Ocak 2017 Cuma

Kolay SQL Server ve dosya yedekleme mekanizması


Merhaba,

Uzun süredir üzerinde çalıştığınız projeniz bilgisayarınızdaki sorun yüzünden erişilemez mi oldu,
ah keşke yedeklemeye önem verseydim mi diyorsunuz.
İşte size  herhangi bir program kurmadan kolayca oluşturabileceğiniz bir yedekleme mekanizması.

diyelim ki
proje dosyalarımız  c:\projelerim  klasöründe
ve  veri tabanı olarakta  MS SQL kullanıyoruz ve ProjeDB adında bir veritabanımız var.

yedeklerimizi   Z:\yedeklerim  isimli bir klasöre alacağız.

Z: diski  bulut bir depolamadan veya varsa bir sunucu alanından bir yer olursa çok daha güzel olur. böylece bilgisayar
tamamen erişilemez olursa yedeklerimiz uzakta olmuş olur.

* şimdi biz önce veritabanı yedeğini  c:\projelerim\_db_yedek  isimli bir klasöre aldıracağız (bu yoksa oluşturun)
* sonra c:\projelerim  klasörünün  tüm içeriğini rar.exe ile şifleri olarak  z:\yedeklerim klasörüne yazacağız.

eğer rar.exe (winrar kurulu ise sistemde winrar klasöründe bulunur.) kullanmak istemiyorsak,
diğer bir yöntem ise  windows'un  robocopy.exe programını kullanarak  tüm c:\projelerimin içeriğini  z:\yedeklerim'e
mirrorlayacağız. yedeklerimizin logunu c:\ klasörüne yazacağız.


1. yöntem : rar.exe kullanarak:
aşağıdaki metni   bir  text dosyaya kopyalayıp yedekle.bat olarak kaydedelim.
-hp parametresi  h=hidden=dosyaların isimlerini gizle
                 p=password=şifre hemen yanında yazan 12345 ise rar dosyasına verdiğimiz şifre
Siz bunu istediğiniz şifreyle değiştirin.
-m5 parametresi en yüksek sıkıştırma seviyesinde sıkıştırması için
-x ler yanlarına konulan dosyaları wilcardları klasörleri  rar dosyasına atmaz (exclude eder)

-----------------------------------------------------------------------------

@ECHO OFF

set tarih=%date: =%
set tarih=%tarih:.=_%
echo %tarih%
ECHO  db yedekleniyor....

sqlcmd -E -S .\sqlexpress -q "exit(BACKUP DATABASE ProjeDB TO Disk='c:\projelerim\_db_yedek\ProjeDB.bak')"

ECHO dosyalar yedekleme lokasyonunda arşiv dosyasına (yedeklerim***.rar) yazılıyor...

C:\PROGRA~1\WinRAR\rar  a -r -x*.bat -x*.exe -x*.mdf -x*.ldf  -hp12345 -m5 Z:\yedeklerim\yedeklerim_%tarih%.rar  C:\projelerim\*.*

ECHO Bitti. 

-----------------------------------------------------------------------

2. yöntem : robocopy.exe kullanarak:
aşağıdaki metni  bir  text dosyaya kopyalayıp yedekle.bat olarak kaydedelim.
burada 2 kere robocopy çalıştırılma sebebi ilkinde klasör yapısı olduğu gibi karşıya boş dosyalar olarak
oluşturuluyor (parçalanma=defragmantasyonu engellemek için)
2nci robocopy ise kopyalama işlemini yapıyor.

--------------------------------------------------------

@ECHO OFF

set tarih=%date: =%
set tarih=%tarih:.=_%
echo %tarih%
ECHO db yedekleniyor....


sqlcmd -E -S .\sqlexpress -q "exit(BACKUP DATABASE ProjeDB TO Disk='c:\projelerim\_db_yedek\ProjeDB.bak')"

ECHO dosyalar yedek lokasyonuna kopyalanıyor...

robocopy.exe "c:\projelerim" "Z:\yedeklerim" /CREATE /E /DCOPY:T /NP /R:0 /COPY:DAT /LOG+:c:\yedekleme_log_%tarih%.txt /XF "*.exe" "*.mdf" "*.ldf"
robocopy.exe "c:\projelerim" "z:\yedeklerim" /MIR /DCOPY:T /NP /R:0 /COPY:DAT /LOG+:C:\yedekleme_log_%tarih%.txt /XF "*.exe" "*.mdf" "*.ldf"

ECHO Bitti.



-----------------------


komutlardaki sqlcm  komutu komut satırında sql'e bağlanıp query çalıştırmak için kullanılmaktadır.
burada  bağlı olan kullanıcı yetkisi ile trusted olarak eriştiği için -E komutu ile girdik.
yoksa -U ve -P parametreleri ile kullanıcı şifre belirtmek gerekiyordu.
ayrıca yedekleme query bloğunu  exit()  içine alarak işlemden sonra sqlcm'den çıkıp sıradaki robocopy komutuna gelebilsin
diye...



daha sonra  windows  Görev Zamanlayıcısına (Task Scheduler) bu yedekle.bat dosyasını belirli sürelerde çalıştırması için bir Görev ekleyebiliriz.


Kolay gelsin....

Bu blog kaydının yeni/güncellenmiş  versiyonu için tıklayınız...


7 Ocak 2017 Cumartesi

5 Ocak 2017 Perşembe

Sql kullanarak yazılım işimizi hızlandırmak

Merhaba,

Kod yazarken bize angarya olarak gelen şeyleri sql kullanarak
nasıl oluşturabileceğimizden bahsedeceğim. Buradaki örneklerden yola çıkarak benzer işlerimizi kolaylaştırabiliriz.
Aynı işlemi excel ile de yapabiliriz, önemli olan elindeki aracı işini kolaylaştırmak için nasıl kullanacağını bilmektir.

Veritabanında tblFirmalar diye bir tablomuz var. Ve biz bu tabloya ait bir Class yazıyoruz.
Tüm sütunları birer property olarak tek tek yaz tip değişkenini ayarla gibi uzun zahmetli işlerle uğraşma yerine
hazırda beklettiğiniz aşağıdaki sqlin sadece tablo adı kısmını değiştirip tüm tablolalarınız için bu işlemi uygulayabilirsiniz.
ben sadece int, string, bool ve datetime için c# karşılığını yazdım
başka bir sütun tipiniz varsa bunu when x then tip kısmında ayarlamanız gerekiyor.
buradaki veritabanı tiplerinin sayısal değerlerini
select * from sys.columns where object_id= OBJECT_ID('tblFirmalar','U')
yazdığımızda system_type_id sütununda görebiliriz.

şimdi
public int ID {get;set;}
gibi tüm sütunlar için bunu oluşturan sorguyu yazalım.

select
'public ' +
case system_type_id
when 56 then 'int'
when 231 then 'string'
when 61 then 'DateTime'
when 104 then 'bool'
else 'string'
end
+ ' ' + REPLACE(name,' ','_') + ' { get; set; } '
from sys.columns where object_id= OBJECT_ID('tblFirmalar','U')


sonra kodumuzda bir yerde bu objeden f isimli bir instace oluşturup bunun propertylerini
o sıra oluşmuş olan datarow (dr) dan doldurmduğumuz durumunda tüm sütunlar için tek tek
bunun gibi yazmamız gerekiyor.
f.ID=Convert.ToInt32(dr["ID"]);

Bu işlemi bizim için yapan sorgumuz da şöyle olacak:


select
' f.' + REPLACE(name,' ','_') + ' = ' +
case system_type_id
when 56 then ' Convert.ToInt32'
when 231 then 'Convert.ToString'
when 61 then 'Convert.ToDateTime'
when 104 then 'Convert.ToBoolean'
else 'Convert.ToString'
end
+ '(dr[' + char(34) + REPLACE(name,' ','_') + char(34) + ']);'
from sys.columns where object_id= OBJECT_ID('tblFirmalar','U')