Merhaba,
Bir önceki Entity Framework – Code First İle Stored Procedure Oluşturma başlıklı yazımda EF’de nasıl SP oluşturulduğunu detaylıca irdelemiştik. Bu yazımızda ise EF’de SP nasıl kullanılır? sorusunun cevabını aynı hassasiyette vereceğiz.
EF – Code First yaklaşımında SP kullanmak istiyorsak eğer yapmamız gereken oldukça basittir. Elimizde aşağıdaki gibi bir SP olduğunu varsayarsak eğer;
CreateStoredProcedure(
"dbo.OrnekSP",
p => new
{
},
body:
@"
Insert Ogrenciler Values('Gençay', 'Yıldız', 'Artvin')
"
);
bu SP’yi aşağıdaki gibi çalıştırabiliriz.
OkulDBContext Veri = new OkulDBContext();
Veri.Database.ExecuteSqlCommand("OrnekSP");
Context sınıfı üzerinden veritanında bir SQL sorgusunu “.Database.ExecuteSqlCommand” komutu ile çalıştırabiliyoruz. Haliyle ExecuteSqlCommand metoduna verdiğimiz sorgu ilgili veritabanı üzerinde çalıştırılacaksa, o sorgu yerine SP’mizin ismi olan “OrnekSP” sorgusunu yazıyor ve çalıştırıyoruz.
SP’mizin içeriği Insert sorgusundan oluştuğu için haliyle çalışıp çalışmadığını “Ogrenciler” tablosunu kontrol ederek anlayabiliriz.
Gördüğünüz gibi SP’mizi başarıyla çalıştırabildik.
Peki… Şimdide parametre alan bir SP oluşturalım ve onu kullanalım.
CreateStoredProcedure(
"dbo.OrnekParametreliSP",
p => new
{
OgrenciID = p.Int(),
Adi = p.String(),
SoyAdi = p.String(),
Memleketi = p.String()
},
body:
@"
Update Ogrenciler Set Adi = @Adi, SoyAdi = @SoyAdi, Memleketi = @Memleketi where OgrenciID = @OgrenciID
"
);
Gördüğünüz gibi SP’miz “OgrenciID”, “Adi”, “SoyAdi” ve “Memleketi” olmak üzere dört adet parametre almaktadır.
OkulDBContext Veri = new OkulDBContext();
SqlParameter pOgrenciID = new SqlParameter("@OgrenciID", 1);
SqlParameter pAdi = new SqlParameter("@Adi", "Kür");
SqlParameter pSoyAdi = new SqlParameter("@SoyAdi", "Şad");
SqlParameter pMemleketi = new SqlParameter("@Memleketi", "Ötüken");
Veri.Database.ExecuteSqlCommand("OrnekParametreliSP @OgrenciID, @Adi, @SoyAdi, @Memleketi", pOgrenciID, pAdi, pSoyAdi, pMemleketi);
Yukarıdaki gibi “OrnekParametreliSP” isimli SP’yi çalıştırdığım parametre sırasına dikkat ederek gereken değerleri göndermekteyim. Tabi bu değerleri gönderirken her bir parametreyi SqlParameter tipinden bir nesnede tutmakta ve ExecuteSqlCommand metodunu çağırırken sorgu içerisinde parametre değerlerini vermekteyim. Nihayetinde parametre tanımlarken verdiğimiz sıra, bu şekilde kullanımda da öncelik önemine sahip olduğu için parametreleri gönderirken bu sıralamaya dikkat etmekteyim.
Şimdide output bir parametre alan SP üzerinde çalışmamızı yapalım.
CreateStoredProcedure(
"dbo.OrnekOutPutParametreliSP",
p => new
{
OutParametre = p.String(outParameter: true)
},
body:
@"
Select @OutParametre = 'Gençay YILDIZ'
"
);
Kullanımı ise aşağıdaki gibidir.
OkulDBContext Veri = new OkulDBContext();
SqlParameter pOutParametre = new SqlParameter("@OutParametre", System.Data.SqlDbType.NVarChar)
{
Direction = System.Data.ParameterDirection.Output
};
Veri.Database.ExecuteSqlCommand("OrnekOutPutParametreliSP @OutParametre out", pOutParametre);
Eğer bu şekilde bir kullanıma yeltenirsek aşağıdaki hatayı alacağız.
An unhandled exception of type ‘System.InvalidOperationException’ occurred in EntityFramework.SqlServer.dll
Additional information: String[0]: Size özelliğinin 0 olan boyutu geçersiz.
Peki bu hata neden kaynaklanmaktadır?
Eğer string(nvarchar) tipinde bir Output parametre kullanıyorsak ve yukarıdaki gibi SqlParameter tipinden bir nesne üzerinde veri taşıyorsak bu nesnenin tutacağı veri aralığının boyunu belirtmemiz gerekmektedir.
Daha doğrusu, Output olarak verilecek string(nvarchar) parametrenin SP’deki aralığı ne ise en az o aralıkta bir parametre oluşturmalıyız.
OkulDBContext Veri = new OkulDBContext();
SqlParameter pOutParametre = new SqlParameter("@OutParametre", System.Data.SqlDbType.NVarChar, int.MaxValue)
{
Direction = System.Data.ParameterDirection.Output
};
Veri.Database.ExecuteSqlCommand("OrnekOutPutParametreliSP @OutParametre out", pOutParametre);
İşte boyutumuzuda constructerdan vererek hatamızı düzeltmiş olduk.
Bakalım pOutParametre isimli parametremize içeriden değer gelmiş mi?
Gördüğünüz gibi ilgili veriyi Output parametremiz getirmiş bulunmaktadır.
Farkındaysanız şuana kadar kullandığımız SP’lerin hiçbiri içerisinde tablo dönen Select sorgusu barındırmamaktadır. Haliyle son olarak geriye bir tablo dönecek sorguyu barındıran SP kullanımını irdeleyelim.
CreateStoredProcedure(
"dbo.OgrencilerSP",
p => new
{
},
body:
@"
Select * from Ogrenciler
"
);
SP sonucunda geriye dönecek tabloyu temsil edecek bir Entity model oluşturulmalıdır.
Eğer ki, SP sonucu dönecek olan tablo farklı işlemler sonucu oluşturulmuş bir tablo ise o tabloyu temsil edecek Entity gerekeceğini baştan söyleyelim. Yok eğer SP sonucu gelen tablolar fiziksel tabloların birebir aynıları ise onları table classları temsil edebilmektedir.
Haliyle yukarıdaki SP sonucunda Ogrenciler tablosu geleceği için “Ogrenciler” tablosunu temsil eden entityi tip olarak kullanabileceğiz.
OkulDBContext Veri = new OkulDBContext();
var Ogrenciler = Veri.Database.SqlQuery<Ogrenci>("OgrencilerSP").ToList();
Yukarıdaki kod bloğunu incelerseniz eğer SP’den dönecek olan bir tablo mevzu bahis olduğu için “SqlQuery” metoduyla çalışmaktayız. Haliyle SP sonucu elde edilen tabloyu satır satır, bu Generic metoda verdiğimiz tipte oluşturduğu nesneler olarak tutmaktadır. Tablonun kolon isimleri ile, tipin property isimleri birbirini destekliyorsa hatasız bu işlemi gerçekleştirecek ve bize veri kümesini ilgili nesne tipinde dolduracaktır.
Gördüğünüz gibi net bir şekilde verilerimizi elde ettik.
Peki SqlQuery metodunda parametreli SP kullanmaya çalışırsak nasıl olur?
Bakalım nasıl oluyormuş…
CreateStoredProcedure(
"dbo.OgrencilerSP",
p => new
{
OgrenciID = p.Int()
},
body:
@"
Select * from Ogrenciler where OgrenciID = @OgrenciID
"
);
Kullanacağımız SP yukarıdadır.
SqlParameter pOgrenciID = new SqlParameter("@OgrenciID", 1);
OkulDBContext Veri = new OkulDBContext();
var Ogrenciler = Veri.Database.SqlQuery<Ogrenci>("OgrencilerSP @OgrenciID", pOgrenciID).ToList();
Evet… Gördüğünüz gibi yukarıdaki işlemlerde parametre konusunda ne yaptıysak, bunda da aynı işlemi gerçekleştirmekteyiz.
Gördüğünüz gibi sorunsuz çalışmaktadır.
Sanırım biraz ağır bir yazı oldu… Malumunuz ben internette bu konuda pek fazla Türkçe kaynak olmaması üzerine olabilecek tüm hata ve durumları kapsayacak bir makale olsun istedim…
Okuduğunuz için teşekkür ederim…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
