Makaleler

 Merhaba arkadaşlar bu makalemizde Mssql sunucu tabanlı veritabanlarının FileStream özelliği ile nasıl kullanıldığı hakkında kısa bilgi vermeye çalışacağım.

 

Öncelikler uygulama geliştirirken veritabanı üzerinde verilerimizi (dosya, doküman, resim, müzik vs) text formatı dışındaki bilgilerimizi nasıl tutacağımız hakkında biliyorum ki hepimiz 1- 2 kez tereddütte düşmüşüzdür. Acaba dosyalarımızı veri tabanında tutsak veritabanı 2 gün sonra şişer mi ya da performans bakımından işlem hamcı sunucu taraflı şişmelere sebep olabilir mi vs…

 

Aslına bakarsak verilerimizi veritabanı üzerinde tutmamız gayet mantıklı, tabi ki bu durumun bize avantaj ve dezavantajlarını da göz ardı etmemiz gerekli.

Eğer verileri tutarsak sistemde harici olarak kullanacağımız klasörleri ortadan kaldırmış olur ve dosya bütünlüğü sayesinde yedek almamız, verileri periyodik olarak tek bir çatı altında tutmamız işimizi çok rahatlatacaktır. 

Tabi ki bu durumlar işimizi kolaylaştırırken elbette performans kaybı yaşayıp verilerin görüntülenmesi biraz daha zaman alacaktır ki bu durum veri tabanın büyüklüğü ve sunucu taraflı donanımın gücüyle de alakalı olarak işleyecektir.

Peki, FileStream özelliği bu sıkıntıların giderilmesine çözüm olacak mı?

Aslına bakarsak yapılan performans testlerinde çözüm olduğu ispatlanmış durumda… Düşünsenize Hotmail’in bu altyapıyı kullandığını (ki öyle J) . Teorik olarak biraz sohbetten sonra aslında örnekleme ile durumu pekiştirelim.

 

Örnek veritabanımız AdvantureWorks olsun ve bu veritabanı üzerinde bulunan ürünlerin resimlerini filestream özelliği sayesinde işleyelim.

İlk olarak sistemimizdeki veritabanı sunucumuzun filestream  acsess level durumunu yanı filestream olayı devreye girince bu cıktı olarak bilgisayarımıza kayıt olan dosyalara ne tipte ulaşım sağlanabilir onunla ilgili izinlerimizi ayarlamak zorundayız.

EXEC sp_configure filestream_access_level, 2 --0 disabled,--1 Transact Sql Access,--2 Win IO Access

2 nolu erişim belirleyicimizle tam erişim sağlamış olacağız. Bu ayarı yaptıktan sonra sql sunucumuzu yeniden başlatmamız da fayda olabilir.

Bu işlemi tsql komutu haricinde sunucu configuration alanındaki sunucu instancemizin özellikleri bölümünden de gerçekleştirebiliriz.

Daha sonra kurban olarak seçtiğimiz veritabanımızın üzerinde gerekli düzenlemeleri sırasıyla yapalım.

 

use AdventureWorks

Go

 

 EXEC sp_configure filestream_access_level, 2

  -- 0 : Disable , 1 : Transact Sql Access ,    Full Accsess

  GO

    RECONFIGURE

    GO

 

 

ALTER DATABASE AdventureWorks ADD

FILEGROUP AdventureWorksFs CONTAINS FILESTREAM;

 

İlk olarak bir tane AdvantureWorksFs adlı filegrubu  veritabanımıza ekliyoruz. Ardından işlemler esnasından veritabanın kalıcı olarak tutacağı dosya ve klasör ayarlarını belirliyoruz.

 

 

GO

alter DATABASE AdventureWorks ADD FILE (

       NAME = AdventureWorksFs,

       FILENAME = 'D:\FsDosyalari\AdventureWorks')

TO FILEGROUP AdventureWorksFs;

 

Oluşturduğumuz Filegrubu filestream ile açıyoruz.

 

GO

ALTER TABLE dbo.AdventureWorks

SET (FILESTREAM_ON = AdventureWorksFs)

 

Daha ve son olarak verilerin çıkartılmasını sağlayacak işlemlere geçiyoruz, buraya geçmeden önce verilerimizin tutulduğu tabloda olması gereken unique idye sahip bir kolon bulunması gerekmektedir onun için bir sonraki hamlede unique bir kolon ekleyerek işlemelerimize devam ediyoruz.

 

Go

 

ALTER TABLE dbo.Product.Photo

ALTER COLUMN RowId ADD ROWGUIDCOL

Go

Şimdi eski verilerimizi kendi oluşturacağımız kolon üzerine alacağız ve bu esnada filestream özelliğini veritabanı çağırarak veritabanındaki verilerin belirlediğimiz klasöre yazılmasını sağlayacağız.

 

ALTER TABLE dbo.dbo.Product.Photo ADD  DataFs varbinary(max) FILESTREAM  NULL

 

Go

 

UPDATE dbo.Product.Photo SET DataFs = LargePhoto;

 

GO

Eski bilgilerin bulunduğu kolonu silip  en son satırdaki procedure ile oluşturduğumuz Datafs adlı konunu isimi silinen kolonun ismi ile değiştireceğiz.

ALTER TABLE dbo.Product.Photo

DROP COLUMN LargePhoto;

 

GO

EXEC sp_rename 'AdventureWorks.dbo.Product.Photo.DataFs', 'LargePhoto', 'COLUMN';

Sonuç olarak veriler yeni oluşturulan tablo kolonuna aktarılırken örnek dosyaları belirttiğimiz klasöre çıkartıldı. Artık veritabanı üzerinde bir sorgu çalıştırıldığında veri ilk olarak temp e alınmayacak , web sayfalarında sorguya bağlı olarak süre dolaylı yollardan kısalacak, Windows uygulamalarda işlem hacmini daha da minimal seviyede tutacaktır.

Detaylı performans test bildirimi için tıklayınız.

Bir sonraki makalede görüşmek üzere arkadaşlar 

 Nested Level 32 Hatası Ve Kotarımı

 

Merhabalar arkadaşlar bu makalemizde Mssql server database sistemlerinde iç içe işlem yapan procedurde 32 katman aşağıya kadar girmemizi sağlayan ve 32 katmandan yanı dönüşten sonra işlem yapmamızı engelleyen nestedlevel32 hatasını çözümleyeceğiz, tabiî ki yardımcımız CURSORlar  

 

Düşünün ki bir kategori tablomuz var ve bu tablomuzda ilişkilendirilmiş üst kategori ve alt kategori mantığı söz konusu siz eğer bir kategori silinirse ona bağlı olan alt kategorilerde silinsin istiyorsunuz silinme esnasında alt kategorisi bulunan kategorileri bir üst sınıfa çıkartarak dallanmış yapıyı korumaya çalışacaksınız ya da hepsini sileceksiniz.

 

Lafı Çok uzatmadan bu hataya karşı ya da önleme karşı nasıl bir çözüm sunabiliriz. Hemen bahsedelim…

 

--@Id Ana Id Çocuklar annelerine bağlı J

--PidId çocuk Yanı ana Id

 

CREATE TRIGGER [dbo].[KategoriSil]

   ON  [dbo].[Kategoriler]

   AFTER DELETE

AS

BEGIN

                 

                declare  cur  cursor local fast_forward for select ID From Deleted --- silinmiş Idyi temp databasinden alıyoruz. Local tanımlamayı unutmayınız ki database oluşturulurken bu şecenek global olarak default olabilir

                open cur   --- bir adet cursor oluşturup

                declare @Id uniqueidentifier

 

                fetch next from cur into @Id

                while @@fetch_status =0  -- gelecek nesne statüsü 0 olana kadar while döngüsünde dönüyoruz.

                begin

                Delete From Kategoriler Where PID=@Id -- Her silindiğinde silinenin Idis bir sonraki gelecek Id oluyor.

                --Update StokKarti Set KategoriID='00000000-0000-0000-0000-000000000000' Where KategoriID=@Id – bu kategoriye ait olan urunleri bu alanda kategorisizler kategorisine taşıyoruz tabili siz istediğiniz şekilde işleyebilrisiniz.

 

                fetch next from cur into @Id – bir sonraki Id getir.

                end

                close cur – cursoru kapatıp

                deallocate cur  -- cursoru olduruyoruz

END

GO

 

 

Bilgi : cursor  kayıtlar arası satır satır dönmemizi sağlar  bu konu ile ilgili de makalelerimizi daha sonra yazalım …

Evet yukarıda belirttiğim gibi bir triger içerisinde nested level engellemesini bu şeklide engelleyebiliriz. 

 

 

İyi çalışmalar dilerim

Rahmi Tuğrul Altın

 using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.ComponentModel.Design;

namespace RTA.BumpSlider

{

    public class Bump : System.Web.UI.WebControls.WebControl

    {

        public enum GirisHizi { fast, slow };

        public enum CikisHizi { fast, slow };

        public int Saniye { get; set; }

        public GirisHizi AnimasyonGirisHizi { get; set; }

        public CikisHizi AnimasyonCikisHizi { get; set; }

 

        public BumItemsCollection Items { get; set; }

 

        protected override void OnLoad(EventArgs e)

        {

            base.OnLoad(e);

            this.Page.ClientScript.RegisterClientScriptBlock(GetType(), "blok", Ayarlar(), true);

        }

        public Bump()

            : base()

        {

            Items = new BumItemsCollection();

 

        }

        // javascript ayarları yapıldı bu sayede Çalışma zamanında  scriptimizin içine bir adet resim dizi ekledik

        private string Ayarlar()

        {

 

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("");

            sb.AppendLine("var saniye=" + Saniye);

            int i = 0;

            sb.Append("var dizi=[");

            foreach (BumpItems bp in Items)

            {

                if (i == 0)

                {

 

                }

                else

                {

                    sb.Append("'" + bp.ResimUrl + "',");

                }

                i++;

 

            }

            sb.AppendLine("'];").Remove(sb.ToString().Length - 6, 4).Insert(sb.ToString().Length, "];");

            sb.AppendLine("");

            sb.AppendLine("var i =1;");

 

            sb.AppendLine(" setInterval(ResimDegis, saniye);");

 

            sb.AppendLine("function ResimDegis() {");

            sb.AppendLine("if (i == dizi.length) { i = 0; }");

            sb.AppendLine("$(\"#rtaimg1\").slideUp('" + AnimasyonGirisHizi.ToString() + "', function() { $(this).attr('src', dizi[i]); i++; }).slideDown('" + AnimasyonCikisHizi.ToString() + "');");

            sb.AppendLine("}");

 

            return sb.ToString();

 

        }

 

        private string CssBas()

        {

      return  "#rtaimg1 { width:"+this.Width.ToString()+"; height:"+this.Height.ToString()+";}";

       

        }

        protected override void OnPreRender(EventArgs e)

        {

            base.OnPreRender(e);

        

 

            HtmlGenericControl ht = new HtmlGenericControl("img");

            ht.Attributes.Add("id", "rtaimg1");

            ht.Attributes.Add("src", Items[0].ResimUrl);

 

            this.Controls.Add(ht);

 

        }

        protected override void OnInit(EventArgs e)

        {

            base.OnInit(e);

            this.Page.ClientScript.RegisterClientScriptInclude("jquery", "http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js");

 

            HtmlGenericControl ct = new HtmlGenericControl("style");

            ct.InnerHtml = CssBas();

            this.Page.Header.Controls.Add(ct);

//Genişlik ve yükseklik için Css olutruyoruz  değerleri 0 verirseniz resim boyutunda patlayacaktır..

 

 

        }

    }

}

 

 

Bu clasımızı Collection sınıfı kullanarak türettik yalnız Itemsleri almak için…

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

 

namespace RTA.BumpSlider

{// Nesne collectionu oluşturduk...

 

    public class BumpItems

    {

 

        //istenecek Itemleri burda oluşturup  collectiona atacagız...

        public string ResimUrl { get; set; }

    

 

        public BumpItems(string _ResimUrl) :

            base()

        {

            ResimUrl = _ResimUrl;

          

        }

    }

    public class BumItemsCollection : CollectionBase

    {

        //listemizi verilen itemlerle doldurup collection içinde tutucagız..

 

        public BumpItems this[int index]

        {

            get { return (BumpItems)base.List[index]; }

            set { base.List[index] = (BumpItems)value; }//veri basıp cekmek için get set yaptık verilen itemleri listenin indexine koyduk.

        }

        public void Add(BumpItems value)

        {

            base.List.Add(value);

        }

        public void Remove(BumpItems value)

        {

            base.List.Remove(value);

        }

    }

 

}

 

 

Daha sonra Sayfamıza bu şekilde register ettik

 

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="rtaBumpDeme._Default" %>

<%@ Register Assembly="RTA.BumpSlider" Namespace="RTA.BumpSlider" TagPrefix="rtab" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

   <rtab:Bump runat="server" ID="rtabump1" AnimasyonCikisHizi="fast"

            AnimasyonGirisHizi="fast" Saniye="2000" />

    </div>

    </form>

</body>

</html>

 

 

 

Kod Tarafından ise itemslarına nesne ekledik…

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace rtaBumpDeme

{

    public partial class _Default : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

 

            rtabump1.Items.Add(new RTA.BumpSlider.BumpItems("http://www. rtayazilim.com/BuyukResimler/024b147e-7bc9-49ca-aba4-e92da7e2224e.jpg"));

 

            rtabump1.Items.Add(new RTA.BumpSlider.BumpItems("http://www.rtayazilim.com/BuyukResimler/37cd8323-6d80-4aa0-a25d-72bab3206e88.jpg"));

            rtabump1.Items.Add(new RTA.BumpSlider.BumpItems("http://www. rtayazilim.com/BuyukResimler/024b147e-7bc9-49ca-aba4-e92da7e2224e.jpg"));

 

         

        }

    }

}

 

 

 

Artık elimizde bir adet dinamik Resim sliderı mevcut istediğimiz gibi kullanabiliriz Databaseden gelen resimleri ekleyip  sırayla akmasını sağlayabiliriz Enumlar sayesinde hızını saniye Prop .ile de resim akış hızını  düzenleyebiliriz…

Saygılarımla bir sonraki makale de görüşmek üzere.

 İndirmek için tıklayınız.

Not: Jquery bölümü örnek kodlama olarak verilmiştir.

  Merhaba Arkadaşlar ister masaüstü programlarda isterse Web ortamında Kullanıdığımız uygulamalarda veri güvenliğini korumak için için bir dizi yöntemlere başvururuz. .Net' in bize sunduğu nimetlerden yaralanmak için bizi engelleyen bişey göremiyorum :). Bu makalemizde verilerin RijndaelManaged   nasıl şifrelendiğini ve nasıl geri döndürüldüğünü inceleceğiz. 
 

using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

using System.Security.Cryptography;

 

namespace RTAYazilim

{

    public class Cryptoloma

    {

        /// <summary>

        /// Şifrelenecek Dosya bölümü için gerekli alan

        /// </summary>

        /// <param name="KaynakDosyaYolu">Şifrelenecek Dosya Yolu  String Değerde Olacaktır.</param>

        /// <param name="KayitEdilecekDosyaYolu">Şifrelenmiş Dosyanın Saklanacagı Yolu Temsil Eder.Strin değerde olacaktır.</param>

        /// <param name="Sifre">Temin Edilecek Sifre RijndaelManaged  ile Şifrelenecektir. Mutlaka 126 ,128,256 Bitlik Değer olmalıdır</param>

        /// <returns>bool(tek değer)</returns>

        public static bool EncryptEt(stringKaynakDosyaYolu, string KayitEdilecekDosyaYolu, stringSifre)

        {

            bool kontrol = true;

            try

            {

 

                UnicodeEncoding UE = newUnicodeEncoding();

                byte[] Anahtar = UE.GetBytes(Sifre);

 

                string SifrelenmisDosya = KayitEdilecekDosyaYolu;

                FileStream Fs = newFileStream(SifrelenmisDosya, FileMode.Create);

 

                RijndaelManaged RMCrypto = newRijndaelManaged();

 

                CryptoStream cs = new CryptoStream(Fs,

                    RMCrypto.CreateEncryptor(Anahtar, Anahtar),

                    CryptoStreamMode.Write);

 

                FileStream fsgiris = newFileStream(KaynakDosyaYolu, FileMode.Open);

 

                int veri;

                while ((veri = fsgiris.ReadByte()) != -1)

                    cs.WriteByte((byte)veri);

 

                fsgiris.Close();

                cs.Close();

                Fs.Close();

            }

            catch

            {

                kontrol = false;

            }

 

            return kontrol;

 

        }

 

        /// <summary>

        /// şifresi Çözülecek Dosya alanı

        /// </summary>

        /// <param name="KaynakDosya">Şifrelenmiş Dosya Yolu</param>

        /// <param name="KayitEdilecekDosyaYolu">Şifresi Çözülecek Dosya Yolu</param>

        /// <param name="Sifre">Şifrelenmiş Dosya için verilen şifre Mutlaka 126 ,128,256 Bitlik Değer olmalıdır</param>

        /// <returns>bool(tek değer)</returns>

        public static bool DecryptEt(string KaynakDosya,string KayitEdilecekDosyaYolu, string Sifre)

        {

            bool kontrol = true;

            try

            {

                UnicodeEncoding UE = newUnicodeEncoding();

                byte[] Anahtar = UE.GetBytes(Sifre);

 

                FileStream fsgiris = newFileStream(KaynakDosya, FileMode.Open);

 

                RijndaelManaged RMCrypto = newRijndaelManaged();

 

                CryptoStream cs = newCryptoStream(fsgiris,

                    RMCrypto.CreateDecryptor(Anahtar, Anahtar),

                    CryptoStreamMode.Read);

 

                FileStream fscikis = newFileStream(KayitEdilecekDosyaYolu, FileMode.Create);

 

                int veri;

                while ((veri = cs.ReadByte()) != -1)

                    fscikis.WriteByte((byte)veri);

 

                fscikis.Close();

                cs.Close();

                fsgiris.Close();

            }

            catch

            {

                kontrol = false;

            }

            return kontrol;

        }

    }

}

 

 
yukarıda belirtiğimiz gibi kodlarımızı düzenledikten sonra elimizde artık bir kütüphane mevcut yapmamız gereken tek şey bu kütüphanemizi bir projeye referans ederek gerekli bilgileri ve overloadları sağlamak. Kütüphanemizi denemek için hemen bir Windows Aplication oluşturup  aşağıdaki kodları yerleştirelim.

 

 

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using MobilLife;

using System.Net.NetworkInformation;

using System.IO;

 

namespace Cryto

{

    public partial class Form2 : Form

    {

        public Form2()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            OpenFileDialog op = new OpenFileDialog();

            op.ShowDialog();

            FileInfo fi = new FileInfo(op.FileName);

 

            SaveFileDialog sv = new SaveFileDialog();

            string strm = fi.Extension;

            strm = strm.Remove(0, 1);

            sv.Filter = strm + "(*" + fi.Extension + ") | *."+fi.Extension;

            sv.ShowDialog();

            if (Cryptoloma.EncryptEt(op.FileName, sv.FileName, textBox1.Text))

                MessageBox.Show("OK");

            else

                MessageBox.Show("Olmadı");

 

        }

 

        private void button2_Click(object sender, EventArgs e)

        {

            OpenFileDialog op = new OpenFileDialog();

            op.ShowDialog();

            FileInfo fi = new FileInfo(op.FileName);

 

            SaveFileDialog sv = new SaveFileDialog();

            string strm = fi.Extension;

            strm = strm.Remove(0, 1);

            sv.Filter = strm + "(*" + fi.Extension + ") | *." + fi.Extension;

            sv.ShowDialog();

            if (Cryptoloma.DecryptEt(op.FileName, sv.FileName, textBox1.Text))

                MessageBox.Show("OK");

            else

                MessageBox.Show("Olmadı");

        }

 

        private void Form2_Load(object sender, EventArgs e)

        {

            System.Net.NetworkInformation.NetworkInterface[] nf = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();

 

            foreach (NetworkInterface item in nf)

            {

                if (item.NetworkInterfaceType == NetworkInterfaceType.Ethernet)

                {

                    textBox1.Text = item.GetPhysicalAddress().ToString().Substring(0, 8);

                }

 

            }

        }

    }

}

 

 

Yukarıda ki uygulamada şifreleme anahtarı olarak kullanılan bilgisayarın Mac Idsini  bastık unutulmamalıdır ki şifremiz 126,128 ya da 256 bitlik bir içeriğe sahip olmalıdır.

 

Saygılarımla Rahmi Tuğrul ALTIN

 

Not:Codeproject ve Msdn den yardım alınmış basit ve işlevli bir hale getirilmiştir.