Ado.Net Entity Framework 4.0 - Stored Procedures ve Complex Types

Merhaba Arkadaşlar,

Ado.Net Entity Framework 4.0 ile birlikte gelecek/gelmekte olan yeniliklerden birisi de, Stored Procedure' lerin dönüş tipi ile alakalıdır. Henüz tam olarak bitirilememiş olan bu özellik şu anki haliyle bir Stored Procedure' den geriye karmaşık bir tipinin(Complex Type) döndürülebilmesine izin vermektedir. Bunun için Designer tarafında destek sunulmaktadır. Aslında önceki Ado.Net Entity Framework sürümünde bir Stored Procedure' ün Entity modeli içerisine eklenmesi sonrasında dönüş kümesinin Scalars veya Entities olarak kullanılması sağlanabilmekteydi. Ancak bir Stored Procedure çıktısının Complex Type bazlı olaraktan kod tarafında ele alınamayışı da de önemli bir eksiklikti. Bakalım 4.0 versiyonunda bu eksikliği gidermek adına neler yapılmış. Yazımızın ilerleyen kısımlarında bu özeliği anlamaya çalışıyor olacağız.

İlk olarak kendimize kobay bir Stored Procedure seçelim WinkBu amaçla Adventure Works veritabanında yer alan uspGetManagerEmployees Stored Procedure' ünü kullanabiliriz. Bu procedure parametre olarak ManagerID isimli int tipinden bir dğer almakta ve aşağıdaki örnek çıktıyı üretmektedir.

Pekala Stored Procedure' ümüzün çıktısı, RecursionLevel,ManagerID,ManagerFirstName, ManagerLastName, EmployeeID, FirstName ve LastName alanlarının karşılıklarını özellik(Property) olarak içeren sınıfa ait nesne örneklerinden oluşan bir nesne kümesi ile ifade edilebilir. Bunu gerçekleştirmek için Visual Studio 2010 Ultimate Beta 2 sürümünde oluşturacağımız Console uygulamamıza Adventure Works veritabanı için yeni bir Ado.Net Entity Data Model öğesi ekleyip sadece uspGetManagerEmployees SP' sini seçtiğimizi düşünelim.

Şimdi adım adım ilerleyerek Complex Type üretimini gerçekleştireceğiz.

  1. İlk olarak Model Browser ve AdventureWorksModel.Store kısmından ilgili Stored Procedure adına sağ tıklanıp Add Function Import seçimi yapılmalıdır.
  2. Seçimin ardından gelen ekranda Get Column Information düğmesine basıldığı takdirde ilgili Stored Procedure' den dönen sonuç kümesi için uygun olan kolon bilgilerinin getirildiği görülür. Burada hem EDM Type hemde SQL Type bilgileri yer almaktadır.
  3. Sonraki adımda ise Create New Complex Type düğmesine tıklanarak Stored Procedure' ün sonuç kümesi için gerekli sınıfın üretilmesi sağlanır.
  4. İstenirse üretilen tip adı Complex kutucuğundan değiştirilir(Biz örneğimizde tip adını ManagerEmployees olarak yeniledik)
  5. Ok tuşuna basılarak işlem tamamlanır.

Aşağıdaki şekilde bahsetmiş olduğumuz adımlar görsel olarak özetlenmektedir.

Şimdi arka planda neler olduğuna bir bakalım. İlk olarak Entity Data Model tarafında söz konusu Stored Procedure için bir Return Type ve Mapping Details kısmında gerekli kolon-özellik eşleştirmelerinin yapıldığı görülür.

Buna ek olarak Return Type için kod tarafında ManagerEmployees isimli ComplexObject türevli bir sınıfın üretildiği gözlemlenir. Class Diagram görüntüsünde bu durum açık bir şekilde izlenebilmektedir.

Çok doğal olarak söz konusu Stored Procedure' ün kod içerisinde kullanılabilmesi için gerekli özelliğin de AdventureWorksEntities Context tipi içerisine eklendiği görülebilir.

Dikkat edileceği üzere uspGetManagerEmployees isimli özelliğin(Property) dönüşü ObjectResult<ManagerEmployees> tipindendir. Bu tip IEnumerable<T> ve IEnumerable arayüzlerini(Interface) implemente ettiğinden LINQ sorgularında kaynak veri olarak kullanılabilir.

Dilerseniz birde söz konusu Stored Procedure' e ait çıktıyı örnek kod parçasında değerlendirmeye çalışalım. Bunun için aşağıdaki gibi basit bir kodlama yapmamız yeterli olacaktır.

using System;
using System.Data.Objects;
using System.Linq;

namespace SPAndComplexType
{
    class Program
    {
        static void Main(string[] args)
        {
            using (AdventureWorksEntities context = new AdventureWorksEntities())
            {
                ObjectResult<ManagerEmployees> resultSet=context.uspGetManagerEmployees(16);

                var subResult = from me in resultSet
                                where me.FirstName[0] == 'M'
                                select me;

                foreach (var managerEmployee in subResult)
                {
                    Console.WriteLine("{0} {1} {2} {3} {4} {5} {6}",
                        managerEmployee.EmployeeID.ToString(),
                        managerEmployee.FirstName,
                        managerEmployee.LastName,
                        managerEmployee.ManagerFirstName,
                        managerEmployee.ManagerID,
                        managerEmployee.ManagerLastName,
                        managerEmployee.RecursionLevel
                        );
                }
            }
        }
    }
}

Örnek kod parçasında uspGetManagerEmployess özelliği çağırılmış ve ManagerID değeri 16 olan Employee listesinin getirilmesi sağlanmıştır. Bu işlemin arkasından da elde edilen sonuç kümesi üzerinden basit bir LINQ sorgusu çalıştırılmış ve FirstName alanının ilk harfi M olanların listelenmesi sağlanmıştır. Hemen bir hatırlatma yapalım; SQL tarafındaki uspGetManagerEmployees Stored Procedure' ünün çalıştırılması context nesne örneği üzerinden uspGetManagerEmployess özelliğinin çağırılması ile birlikte gerçekleşmektedir. Son olarak uygulamayı çalıştırdığımızda aşağıdaki çıktıyı elde ettiğimizi görürüz.

Böylece geldik bir yazımızın daha sonuna. Ado.Net Entity Framework 4.0 ile ilişkili yenilikleri öğrendikçe sizlerede aktarmaya çalışıyor olacağım. Bu konuda ilk elden bilgi almak isteyen arkadaşlarımızın Ado.Net Team Blog' unu mutlaka takip etmesini öneririm. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.

SPAndComplexType.rar (36,40 kb)

Yorumlar (4) -

  • Merhaba, sql deki gibi komplex sorguları henüz linq ile yapamadığım için stored procedure kullanamaya devam ediyorum. Uygulamamı visual studio 10 trial, silverlight 4 ve entity framework 4 kullanarak windows application geliştiriyorum. Karşılaştığım sorunlar şunlar
    1- System.Data.Objects namespace ini ekleyemiyorum. Hata: System altında data diye namespace yok diyor.
    2- Entity nin bulunduğu namepace den bir instance oluşturmaya çalıştığımda böyle bir namespace yok diye yine hata veriyor. Örnek:
    "(AdventureWorksEntities context = new AdventureWorksEntities()" bu satırı yazdığımda  AdventureWorksEntities bulunamıyor.
    3- Milyon tane siteye ve örneğe baktım. Hepsi aynı şekilde yapmış. Aynı kodu yazıyorum ama nafile 3 gündür bir stored procedure çalıştıramadım Smile
  • Merhabalar,

    Silverlight projesi geliştiriyorsanız eğer solution içerisinde büyük ihtimalle iki projeniz bulunmaktadır. Genellikle veri odaklı işlemler için Silverlight nesnelerini kullandığınız web uygulamasının değerlendirdiği bir servis(Büyük olasılıkla WCF RIA Service veya WCF Data Service) kullanılması önerilir. Bu servis web uygulaması içerisinde yer alırken Entity Framework odaklı olarak veri kaynaklarını kullanabilir. Bu şekilde deneyebilir misiniz?
  • Bir tane silverlight business application yarattım ve solution içinde 2 proje var. DenemeProje.Web projesinde 1 adet Ado.Net Entity Data Model ile seçilmiş birkaç tablo ve 1 de domain service class var. Bu araçlar ile seçtiğim tablolara erişim sağlayabiliyorum. Tablolara okuma ve yazma testleri yaptım.
    Stored procedure aşamalarını tarif etmemde fayda var sanırım.Sizin anlatımınızdan faydalanarak gidersem;

    "Çok doğal olarak söz konusu Stored Procedure' ün kod içerisinde kullanılabilmesi için gerekli özelliğin de AdventureWorksEntities  Context tipi içerisine eklendiği görülebilir." bu aşamaya kadar hepsi doğru gidiyor. Gerekli yerleri kontrol ediyorum ve kodları görüyorum build ettiğimde hata yok.

    AdventureWorksEntities context = new AdventureWorksEntities();      
    ObjectResult<ManagerEmployees> resultSet=context.uspGetManagerEmployees(16);

    Yukarıdaki satırları ben projemde MainPage.xaml içerisinde OnLoad Eventine yazıp resultSet i datagrid ile göstermek istediğimde aldığım hata mesajı şu:

    "The type or namespace name 'Data' does not exist in the namespace 'System' (are you missing an assembly reference?)"

    Bu hatanın sebebi olarak visual studio veya diğer bileşenler hatalı kurulmuş olabileceğini düşünerek kaldırıp yeniden kurdum. Sonuç alamadım. Şimdi bir sanal makina oluşturup herşeyi baştan yapacağım bakalım sonuç ne olacak.

    Yukarıdaki örneği windows app olarak yaptığınız ve benim gözden kaçırdığım başka bir makaleniz var mı? msdn, ch9, silverlight.net, daron yöndem blog, c#nedir, yazgeliştir gibi sitelere baktım ama hiçbirinde windows app olarak stored procedure çalıştıran bir örneğe denk gelmedim.
  • Merhabalar Cem Bey,

    İlk olarak Silverlight uygulamasına eklediğiniz Domain Service' i nerede kullandığınızı sormak isterim. Sanıyorum ki stored procedure erişiminizi ve gerekli result set dönüşünüzü bu domain service içerisindeki bir operasyon ile gerçekleştirirseniz sorun kalmayacaktır. Nitekim Domain Service' in amaçlarından birisi de Siverlight nesnesi içerisinden sunucu tabanlı veri kaynaklarına olan erişimi sağlamaktır.

Yorum ekle

Loading