Data Modelleyici

by Volem April 16, 2011 11:58

Bu aralar profesyonel kullanim amaciyla veritabani modelleme araci bakiyorum. Genel olarak aradigim reverse engineering yapabilmeli, alter ve creation scriptleri generate edebilmeli + genel gecer veritabanlari icin destegi olmali.. Toad Data Modeller opsiyonlardan biri, bir digeri ise Sybase Power Designer ancak iki opsiyon da fiyat olarak pahali geldi. Bana onerebileceginiz free bir tool varsa mutesekkir olurum. Toad Data Modeller 25 entity (table) 'a kadar ucretsiz destek veriyor ancak bu yetmiyor gercek dunyada.

Tags:

Yazılım | SQL

CLR User Defined Functions Part III

by Volem November 23, 2010 10:08

User defined fonksiyonlarin 3. yazisini biraz geciktirdim malesef.. Isler arti bayram tatili araya girince elde olmayan sebepler olustu. Bugun size clr ile tanimlayabileceginiz aggregate fonksiyonlardan bahsedecegim. Eger daha once goz atmadiysaniz yazimin I. ve II. kisimlarini okumanizi tavsiye ederim. Daha onceki kisimlardan da hatirlayacaginiz uzere kullanici tanimli fonksiyonlar tanimlamak icin belirli kurallara uymamiz gerekiyor. Bir aggregate fonksiyon tanimlamak icin oncelikli olarak sinifinizin IBinarySerialize interface'ini implement etmesi gerekiyor. Bu interface bize iki adet metod sunuyor; Read ve Write.. Bu metodlar SQLServer ile CLR arasindaki asil veri akisini saglayan metodlardir. Ornekten de anlasilacagi uzere olusan veriyi sqlserver'a donduren veya sqlserverdan okuyan metodlardir. Bunun disinda sinifinizin 4 adet daha metod icermesi gerekiyor. Bu metodlar; Init, Accumulate, Merge ve Terminate..(Sizlere tavsiyem verdigim ornegi derlerken metodlardan birini cikarin ve bu sekilde olusan assemblyi sql server'a register etmeye calisin.. Zaten alacaginiz hata sizi yonlendirecektir.)

Sirasiyla metodlari anlatmadan once ornek kodu asagida veriyorum. Bu kod ile grupladiginiz bir kolondaki degerleri virgullerle ayirip baska bir kolonda yazabiliyorsunuz. MySQL'de built-in olan concat aslinda tam olarak concat_ws (concat with seperator) aggregate fonksiyonunun implementasyonu oluyor bu ornek. Bu arada MSSQL (T-SQL) built-in aggregate fonksiyonlara bakmak isterseniz lutfen buraya

using System;
using System.Data;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.IO;
using System.Text;

[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToNulls = true,
IsInvariantToDuplicates = false,
IsInvariantToOrder = false,
MaxByteSize = 8000)
]
public class Concatenate : IBinarySerialize
{
private StringBuilder intermediateResult;

public void Init()
{
this.intermediateResult = new StringBuilder();
}

public void Accumulate(SqlString value)
{
if (value.IsNull)
{
return;
}

this.intermediateResult.Append(value.Value).Append(',');
}

public void Merge(Concatenate other)
{
this.intermediateResult.Append(other.intermediateResult);
}

public SqlString Terminate()
{
string output = string.Empty;
if (this.intermediateResult != null
&& this.intermediateResult.Length > 0)
{
output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);
}

return new SqlString(output);
}

public void Read(BinaryReader r)
{
intermediateResult = new StringBuilder(r.ReadString());
}

public void Write(BinaryWriter w)
{
w.Write(this.intermediateResult.ToString());
}
}

Sirasiyla gerceklememiz gereken metodlara bakalim. Aslinda bir constructor olarak dusunebileceginiz Init metodu ile sinifiniz icerisinde yer alan degiskenlerin ilk degerlerini verebilirsiniz. Accumulate metodu ise asil concat isleminin yapildigi yer. Kodtan da anlasilacagi uzere bos olmayan degerleri virgulle ayirarak output'a yaziyoruz. Terminate metodunda ise en son yapmak istediginiz islemleri yapabilirsiniz, ornegimizde en sondaki virgulu kaldirma islemi yapiliyor. Henuz bahsetmedigim merge metodu da iceriginden de anlasilacagi gibi birden fazla concatenate fonksiyonunun birbiri ile anlasmasini saglayacak metodtur.

Son olarak bir user defined aggregate tanimlamak icin sinifiniza 2 adet attribute(ozellik) eklemeniz gerekiyor. Bunlardan birincisi Serializable, digeri ise SqlUserDefinedAggregate. Burada SqlUserDefinedAggregate ozelligi icin bazi named parametre tanimlari goruyorsunuz. Zaten isimleri icerigini anlatiyor ancak diger parametre ve detaylar icin buraya bir goz atabilirsiniz.

Gelelim bu tanimladigimiz sinifimizi nasil SQL server'a tanitacagimiza.. Daha onceki CLRvsSQLServer yazilarimi okuduysaniz, yine oradakine benzer bir tanimlama kullanacagiz.


CREATE ASSEMBLY ClrCode FROM '<DLL_Path>'
GO
CREATE AGGREGATE Concatenate (@input nvarchar(200)) RETURNS nvarchar(max)
EXTERNAL NAME ClrCode.[ArticleCodes.Concatenate]

Herkeslere kolay gelsin...

 

Tags: , ,

C# | SQL

CLR User Defined Functions Part II

by Volem November 01, 2010 14:08

Daha onceki yazimda scalar deger donduren bir fonksiyonu nasil MSSQL Server'a tanittigimizi anlatmaya calismistim. Bu yazimda ise bir T-SQL'deki table-valued fonksiyonu CLR ile nasil tanimlayabilecegimizden bahsedecegim. Table-valued fonksiyonlar bildiginiz gibi bir data listesi seklinde (table) donus degeri olan fonksiyonlardir. Bunun Microsoft CLR karsiligi tahmin edebileceginiz gibi IEnumarable tipindedir. Fazla uzatmadan kod uzerinden anlatmaya calisacagim.


using System;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Data;


namespace ArticleCodes
{
    public class CLRTableValuedFunctions
    {
        private class CustomerResultMember
        {
            public SqlString Name { get; private set; }
            public SqlString Country { get; private set; }

            public CustomerResultMember(SqlString name, SqlString country)
            {
                Name = name;
                Country = country;
            }
        }

        [SqlFunction(FillRowMethodName = "FillRow",
            DataAccess = DataAccessKind.Read)]
        public static IEnumerable GetCompaniesSince(SqlDateTime creationDateStart)
        {
            ArrayList resultCollection = new ArrayList();
            using (SqlConnection conn = new SqlConnection("context connection=true"))
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand("SELECT Name, Country FROM Companies WHERE CreationDate >= @creationDateStart ", conn);
                SqlParameter creationDateParam = cmd.Parameters.Add(
                "@creationDateStart",
                SqlDbType.DateTime);
                creationDateParam.Value = creationDateStart;

                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                    {
                        resultCollection.Add(new CustomerResultMember(sdr.GetSqlString(0), sdr.GetSqlString(1)));
                    }
                }
                return resultCollection;
            }
        }

        public static void FillRow(object CustomerResultMemberObj, out SqlString customerName, out SqlString customerCountry)
        {
            CustomerResultMember crm = (CustomerResultMember)CustomerResultMemberObj;
            customerName = crm.Name;
            customerCountry = crm.Country;
        }
    }
}

Oncelik olarak asil isi yapan metodumuza bakalim.

public static IEnumerable GetCompaniesSince(SqlDateTime creationDateStart)

Bu metod gordugunuz gibi IEnumerable donduren ve ayni scalar fonksiyon tanimindaki gibi (bkz. onceki makale) statik bir metod. Kisaca ArrayList icerisine Select metodu ile belirlenmis ve metod parametresiyle sinirlanmis verileri ekleyip, bu ArrayList'i donduruyor. CLR tanimlamak icin daha once de belirttigim gibi belirli standartlar var. Scalar fonksiyon taniminda iki adet standart tanim yapmaniz gerekiyor, bunlar 1 adet init metod ve bu metodun fillrow metodudur. Init metodu, yani bizim ornegimizde GetCompaniesSince datayi getiren ve isi yapan metoddur. FillRow ise IEnumarable'dan anlamaya SQL server'a bu datayi nasil isleyebilecegini gosteren metoddur. Cunku artik olusacak fonksiyon diger T-SQL query'leri icinde de bir tabloymuscasina kullanabilir. Sonucta konumuz tablo donen fonksiyonlar Smile.

Dikkat edilmesi gereken husus, sadece init metodunuzun icerisinde bir sql connection yapabilirsiniz ancak FillRow metodunda bunu yapamazsiniz. Init metodunda da bunu yapabilmek icin SqlFunction attributenun DataAccess parametresi DataAccessKind.Read seklinde set edilmesi gerekmektedir.

Son olarak bu yeni CLR metodumuzu SQL server'a nasil tanitacagimiz konusu kaldi. Daha onceki yazimda bu tanimlamada yapilan isin detaylari bulabilirsiniz. Burada tekrar etmeden sadece kodu veriyorum.


CREATE ASSEMBLY ClrCode FROM '<DLL_Path>'
WITH PERMISSION_SET = SAFE -- EXTERNAL_ACCESS
GO

CREATE FUNCTION GetCompaniesSince(@CreationDate datetime)
RETURNS TABLE (
   Name nvarchar(50),
   Country nvarchar(50)
)
AS EXTERNAL NAME ClrCode.[ArticleCodes.CLRTableValuedFunctions].GetCompaniesSince

Herkese iyi calismalar.

Tags: , ,

C# | SQL

CLR User Defined Functions Part I

by Volem October 25, 2010 10:12

Microsoft teknolojilerinin ne kadar icli disli oldugunu biliyorsunuzdur. Ornegin siz bir web uygulamasinin icinde Excel sheet, windows uygulamasinin icinde explorer nesnesini cok da ugrasmadan kullanabilirsiniz. Bu iliskiye benzer bir iliski ile C# veya VB.NET de yazdiginiz bir metodu bir MS SQL Server fonksiyonuna nasil cevirebilirsiniz sorusunu yanitlamaya calisacagim. Bu 3 alt makaleden olusan yazi dizisinin 1.si..

Microsoft SQL 2005 Server'dan itibaren CLR(Common Language Runtime) User defined functions (kullanici tanimli fonksiyonlar) tanimlamamiza izin veriyor. Bu yazimda oncelikli olarak size scalar bir deger donduren bir fonksiyonu sql server'a nasil tanitacagimizi anlatmaya calisacagim.

Oncelikle C# kodumuza bir goz atalim..

using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

namespace ArticleCodes
{
    public class CLRScalarValuedFunction
    {
        [SqlFunction(DataAccess=DataAccessKind.Read)]
        public static int GetCompanyCount()
        {
            using (SqlConnection conn = new SqlConnection("context connection=true"))
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand("SELECT COUNT(*) AS companyCount FROM Companies", conn);
                return (int)cmd.ExecuteScalar();
            }
        }
    }
}

Bir scalar fonksiyon tanimlamak icin oncelikle metodumuzun static bir metod olmasi gerekiyor. Yukaridaki kod kendini anlatiyor diye dusunuyorum. Burada dikkatinizi cekmek istedigim kisim SqlConnection tanimi.. Dikkat ederseniz alisila gelmis connection string'lerden biraz farkli.

SqlConnection conn = new SqlConnection("context connection=true")

Peki neden boyle bir tanim yaptik ve bu tanim bize ne anlatiyor. Oncelikli olarak biz bu metodu SQL Server'a tanitacagiz ve bu bir veritabanina ya da master'a tanimli olacaktir. Dolayisiyla metodu kullanacak olan kisi zaten bir veritabani baglantisi yapacak ve ardindan bizim metodumuzu kullanacaktir. Biz iste bu baglantidaki yetkileri ile bu metodu cagiriyoruz. Dolayisiyla guvenli bir baglanti yapiyoruz. Eger bu metodu cagirma ya da bu veritabanina baglanma ve yahut da veri cekme yetkisi yok ise bu kontrolleri yapmamiza gerek kalmiyor. Context Connection ile ilgili detayli bilgi icin buraya bi goz atabilirsiniz.

Bunun disinda dikkat etmemiz gereken husus metodumuzun giris parametreleri ve donus degeridir. Bunlarin SQL Server tarafindan desteklenen scalar deger tipleri olmasi gerekiyor. Bu konuda da suraya bi bakin derim.

Simdi gelelim bu yazdigimiz ve derledigimiz metodu nasil SQL Server'a tanitacagimiza..

CREATE ASSEMBLY CLRCodes FROM '<DLL'in tam yolu(full path)>'

Bu T-SQL komutunu metodumuzu tanimlamak istedigimiz veritabanimizda calistiriyoruz. Boylece tanimladigimiz dll artik SQL server tarafindan benimsenmis oluyor. Ardindan yapilacak ikinci iş, metodumuzu tanimlamak..

CREATE FUNCTION GetCompanyCount() RETURNS INT
AS EXTERNAL NAME <assembly adi>.[<namespace>.<class adi>].<method adi>

Yani verdigim ornege gore

CREATE FUNCTION GetCompanyCount() RETURNS INT
AS EXTERNAL NAME CLRCodes.[ArticleCodes.CLRScalarValuedFunction].GetCompanyCount

Bu komutlari calistirdiktan sonra goreceksiniz ki assembly altinda CLRCodes adinda bir dll ve Scalar-Valued functions altinda GetCompanyCount adinda bir metod olusturulmustur. Metodu test etmek icin

SELECT [dbo].[GetCompanyCount]()

querisini calistirabilirsiniz.

Ancak kodu test ettiginizde muhtemelen "CLR not enabled" benzeri bir hata alacaksiniz. Buradan da sunu cikariyoruz; SQL Server default olarak sizin .NET kodunuzu desteklemiyor. Bunu desteklemek icin ise asagidaki kodu calistirabilirsiniz.

EXEC sp_configure 'clr enabled' , '1'
go
reconfigure;
go

Umarim isinize yarar...

Tags: , ,

C# | SQL

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen | Modified by Volem

RSS
View Volkan Nazmi Metin's profile on LinkedIn

RevolverMap

Son Eklenen Yazılar

Yazar Hakkında

Sosyal, evli, çocuklu, karısını ve kızını çok seven, gezmeyi seven, spor yapmak isteyen bir mühendis