Özgür Özvarış

Bir yazılımcının kırık dökük dünyası

LinqKit Linq dynamic sql parameter

clock Şubat 11, 2016 13:47 by author OzgurOzvaris

Merhaba Arkadaşlar,

Kaynaklar

What is LINQKit?

Dynamically Composing Expression Predicates

How does PredicateBuilder work

linqpad - adding reference to assembly to using custom types

How does LINQPad reference other classes

Building LINQ Queries at Runtime in C#

LinqPad adds an S to the end of every table

Writing Methods and Classes in LINQPad

Entity Framework te Linq ile yapacağınız geliştirmelerde. ilk karşınıza çıkacak zorluklardan bir tanesi dinamik olarak parametre eklemek.

LinqPad malumunuz uzun süredir linq cümleleri geliştirmek için kullanılan bir araç. Gerek database bağlantılı gerekse database bağlantısı olmadan linq sorgularının çıktılarını inceleyebiliryorsunuz. Bu bloğu sanki LinqPad ile ilgili bası basamakları biliyormuşsunuz gibi bazı ön kabullerle başlayacağım. Bu Ön kabuller.

1 - Temel Linq bilgisi

2 - LinqPad download ve install edilmesi

3 - Database connection oluşturulması

Bu ön kabuller üzerinden devam ederek sizlere dinamik bir linq sorgusu nasıl geliştirilir izah etmeye çalışacağım.

LinqPad adresinden gerekli setup işlemlerini yapıyor ve LinqPad'i açıyorsunuz

 

- Öncelikli olarak Sol menüdeki Add Connection bölümünü tıklayarak connection oluşturmanız gerekmektedir.Default linki kullanarak devam et diyerek connection kurabilirsiniz. (Güncelleme 25.04.2016 )Connection oluştururken "Pluralize" seçeneğinin açık olup olmadığını dikkat edin. Ben kapalı olarak kullandığım için bir müddet neden Expandable komutum çalışmadı diye zaman harcadım. Meğerse tablo adının sonuna "s" eklemiş

 

- Şimdi sıra geldi dinamik parametreler eklememize yardımcı olan LinqKit dll'ini yüklemeye. Bu dll'i nuget yada What is LINQKit? makalesinin altındaki download linki ile yükleyebilirsiniz. 

-  LinqKit kurduğunuz yerden LinqPad'a refernce olarak eklemeniz gerekmektedir. Bunun için F4 Tuşuna basmalısınız. Karşınıza Add Reference penceresi çıkacak. Browse seçilerek LinqKit işaret edildikten sonra, Additional Namespace inmport bölümünden LinqKit adı yazılarak LinqPad'in artık LinqKit'i tanıması sağlanır.

 

- Daha sonra Language seçmelerinden c# statements seçmelisiniz.

 

Ben kendi örneğimde FSYS_USERS tabloma OnlyActive User parametresini test ettim. Siz kendi tablolarınızı çağırarak test yapabilirsiniz. Bu arada Context adı yazmadan direk olarak tablo adı yazdığıma dikkat edin.

var OnlyActiveUsers = true;
Expression<Func<FSYS_USERS, bool>> FSYS_USERSPredicate = p1 => true;

            if (OnlyActiveUsers)
            {
                FSYS_USERSPredicate = FSYS_USERSPredicate.And(z => z.FSTATUS == 'A');
            }
			
var x = from c in FSYS_USERS.Where(c => true).Where(FSYS_USERSPredicate).OrderBy(o=> o.ADSOYAD)
                    select c;

 //           x.ToList();
 
 x.Dump();

 

Yukarıdaki örnekte Eğer OnlyActiveUsers set edilirse linq cumlesine bir predicate daha ekleniyor. Run tuşuna basarak aşağıdaki tablardan dönüş değerlerini, sonuçta oluşan dinamik linq cümlesini ve sql'e giden cümleyi görebilirsiniz. Dump Komutu LinqPad'in aşağıda listeyi görebilmenizi sağlayan bir Extension komutu. ToList'ini alıp aşağıda sonuç tabloayu görmenizi sağlıyor.

Burada gerekli testleri yaptıktan sonra artık sonuç fonksyonumuzu oluşturabiliriz.

public IEnumerable<FSYS_USERS> GetActiveUsersShortInfo(bool OnlyActiveUsers)
        {
            //var FSYS_USERSPredicate = PredicateBuilder.True<FSYS_USERS>();

            //if (OnlyActiveUsers)
            //{
            //    FSYS_USERSPredicate.And(z => z.FSTATUS == "A");
            //}

            //var x = from c in MasterContext.FSYS_USERS.AsExpandable().Where(FSYS_USERSPredicate.Compile())
            //        select c;

            Expression<Func<FSYS_USERS, bool>> FSYS_USERSPredicate = p1 => true;

            if (OnlyActiveUsers)
            {
                FSYS_USERSPredicate = FSYS_USERSPredicate.And(z => z.FSTATUS == "A");
            }

            var x = from c in MasterContext.FSYS_USERS.AsExpandable().Where(c => true).Where(FSYS_USERSPredicate.Compile()).OrderBy(o=> o.ADSOYAD)
                    select c;

            return x.ToList();
        }

 

Bu şekilde tam olarak dinamik bir parametreyi Entity Framework yapımıza eklemiş olduk. Method daki AsExpandable ve Compile komutları LinqKit aracılığı ile gelen extension komutlar.

(Güncelleme 25.04.2016) Eğer c# statement linq cümlesinde bir class yada method kullanmak isterseniz. Bunuda düşünmüşler :) tek yapmanız gereken statement sonunda "}" ile linq bölümünü eklemek ve ardına istediğiniz kadar method ve class ekleyebilirsiniz. Writing Methods and Classes in LINQPad Burada detaylı bir şekilde anlatıyor. Denedim çok güzel çalışıyor.

 

İyi çalışmalar.



Entity Framework Toint64 , Toint32 vs.

clock Eylül 5, 2014 18:33 by author OzgurOzvaris

Merhaba,

Entitiy Frameworkte bir sayıya type cast yapacaksanız convert.ToInt32 gibi metorları kullanmayın runtime da hata alırsınız. Bunun yerine direk olarak (long) diyerek cast edin. Bu durumda sql cast fonksyonu ile sql'e göndericektir.

İyi çalışmalar.



Entity Framework left outer join

clock Eylül 4, 2014 14:03 by author OzgurOzvaris

Merhaba Arkadaşlar,

Kayneklar

Left Outer Joins in LINQ with Entity Framework

LEFT JOIN or RIGHT JOIN using LINQ Entity-Framework

Entity Framework (EF) giriş yazımızda, bazen EF de sql de yapılan basit işlemlerin EF diline göre yapılması gerektiğinden bahsetmiştik. Buna "Left Join " İşlemi güzel bir örnek olabilir. SQL de sadece iki kelime ile yaptığınız left join işlemi iki farlı yöntem var.

Bunlardan birincisi dbSetimizin direk olarak DefaultIfEmpty Metodu ile bağlanması, ikincisi ise dbSetimizin bir variable içine atılıp daha sonra DefaultIfEmpty ile bağlanması.

Standar join işlemi

from o in Orders
join od in OrderDetails on o.OrderID equals od.OrderID
select new {o, od}
SELECT 
    [Extent1].*, [Extent2.*
FROM  [dbo].[Orders] AS [Extent1]
    INNER JOIN [dbo].[OrderDetails] AS [Extent2] ON [Extent1].[OrderID] = [Extent2].[OrderID]

Direk DefaultDefaultIfEmpty

from c in Customers
from o in Orders
    .Where (o => o.CustomerID == c.CustomerID)
    .DefaultIfEmpty()
select new {c, o};
SELECT 
    1 AS [C1], 
    [Extent1].*, [Extent2}.*
    FROM  [dbo].[Customers] AS [Extent1]
    LEFT OUTER JOIN [dbo].[Orders] AS [Extent2] ON ([Extent2].[CustomerID] = [Extent1].[CustomerID])
       AND ([Extent2].[CustomerID] IS NOT NULL)

Değişken içine atarak

var applicantList = (from app in context.APPLICANTs
join a in context.Profiles
on app.Profile_id equals a.PROFILE_ID into output
from j in output.DefaultIfEmpty()
select new { APPLICANT_ID = app.APPLICANT_ID, Applicant_Name = (j == null ? app.Applicant_Name : j.Applicant_Name) }).Take(1000).AsEnumerable();

Complex bir örnek

var x = from i in (DbContext as Krnc_ReSellerEntities).FSYS_LABELS
                    join e in (DbContext as Krnc_ReSellerEntities).FSYS_DICTIONARY
                    //.DefaultIfEmpty()
                       .Where(c => c.FSYS_LANGUAGE.FSLANG_ID == FSLANG_ID)
                        on 
                        new { Table_ID = i.TBL_ID, Field_ID = i.FSLABEL_ID } equals
                        new { Table_ID = e.TBL_ID, Field_ID = e.FIELD_ID }
                        //into output
                        //from k in output.DefaultIfEmpty()
                    join e1 in (DbContext as Krnc_ReSellerEntities).FSYS_DICTIONARY
                        //.DefaultIfEmpty()
                        .Where(c => c.FSYS_LANGUAGE.FSLANG_ID == SecondFSLANG_ID)
                        on
                        new { Table_ID = i.TBL_ID, Field_ID = i.FSLABEL_ID } equals
                        new { Table_ID = e1.TBL_ID, Field_ID = e1.FIELD_ID }
                        into output1
                        from j in output1.DefaultIfEmpty()  
                    //where k.FSYS_LANGUAGE.FSLANG_ID == SecondFSLANG_ID && j.FSYS_LANGUAGE.FSLANG_ID == SecondFSLANG_ID
                    select new LabelDefinitionView {
                        KeyField = i.FSLABEL_ID.ToString() + ";" + e.FSYS_DIC_ID.ToString() + ";" + j.FSYS_DIC_ID.ToString(), 
                        TBL_ID = i.TBL_ID,
                        FSLABEL_ID = i.FSLABEL_ID,
                        LABEL_TYPE = i.LABEL_TYPE,
                        KOD = i.KOD,
                        FSYS_DIC_ID = e.FSYS_DIC_ID, 
                        Description = e.TANIM_ML,
                        Second_FSYS_DIC_ID = j.FSYS_DIC_ID,
                        SecondLang_Description = j.TANIM_ML
                    };
 
SELECT 
    [Extent1].[LABEL_TYPE] AS [LABEL_TYPE], 
     CAST( [Extent1].[FSLABEL_ID] AS nvarchar(max)) + N';' +  CAST( [Extent2].[FSYS_DIC_ID] AS nvarchar(max)) + N';' + CASE WHEN (CASE WHEN ([Extent3].[FSYS_DIC_ID] IS NULL) THEN N'' ELSE  CAST( [Extent3].[FSYS_DIC_ID] AS nvarchar(max)) END IS NULL) THEN N'' WHEN ([Extent3].[FSYS_DIC_ID] IS NULL) THEN N'' ELSE  CAST( [Extent3].[FSYS_DIC_ID] AS nvarchar(max)) END AS [C1], 
    [Extent1].[TBL_ID] AS [TBL_ID], 
    [Extent1].[FSLABEL_ID] AS [FSLABEL_ID], 
    [Extent1].[KOD] AS [KOD], 
    [Extent2].[FSYS_DIC_ID] AS [FSYS_DIC_ID], 
    [Extent2].[TANIM_ML] AS [TANIM_ML], 
    [Extent3].[FSYS_DIC_ID] AS [FSYS_DIC_ID1], 
    [Extent3].[TANIM_ML] AS [TANIM_ML1]
    FROM   [dbo].[FSYS_LABELS] AS [Extent1]
    INNER JOIN [dbo].[FSYS_DICTIONARY] AS [Extent2] ON ([Extent1].[TBL_ID] = [Extent2].[TBL_ID]) AND ([Extent1].[FSLABEL_ID] = [Extent2].[FIELD_ID])
    LEFT OUTER JOIN [dbo].[FSYS_DICTIONARY] AS [Extent3] ON ([Extent3].[FSLANG_ID] = @p__linq__1) AND ([Extent1].[TBL_ID] = [Extent3].[TBL_ID]) AND ([Extent1].[FSLABEL_ID] = [Extent3].[FIELD_ID])
    WHERE [Extent2].[FSLANG_ID] = @p__linq__0',N'@p__linq__1 bigint,@p__linq__0 bigint',@p__linq__1=2,@p__linq__0=1

 



Entity Framework Join

clock Eylül 3, 2014 12:37 by author OzgurOzvaris

Merhaba Arkadaşlar,

Kaynak,

Entity Framework Query for inner join

Entity Framework Join 3 Tables

Entity Framework LINQ joining 5 tables on multiple columns (impossible?!)

Joining tables using more than one column in Linq To Entities

The type arguments cannot be inferred from the query...

Bazen database tarafında tablolar birbiri ile ilişkili olmadığında yada daha esnek conditionlar eklemek istediğinizde (ilişkili ve derinlerdeki tablolara condition eklemek istediğiniz durumlar gibi) EF'ün "Join" komutuna ihiyaç duyabilir siniz.

 Güzel bir örnek olmasından dolayı kaynaklar'dan birinde geçen örneği paylaşıyorum.

from s in db.Services
join sa in db.ServiceAssignments on s.Id equals sa.ServiceId
where sa.LocationId == 1
select s

Eğer birden fazla kolon joinlemek isterseniz...

var match = from t1 in context.cKNA1
             join t2 in context.cKNB1 on 
                    new { t1.KUNNR, t1.RowId } equals 
                    new { t2.KUNNR, t2.RowId }
             join t3 in context.cKNVV on 
                    new { t2.KUNNR, t2.RowId } equals 
                    new { t3.KUNNR, t3.RowId }
             join t4 in context.cKNVH on 
                    new { t3.KUNNR, t3.RowId } equals 
                    new { t4.KUNNR, t4.RowId }
    SELECT t1.KUNNR;


Yada ikinci bir syntax olarak...

from a in Table1s 
from b in Table2s
where a.ID1Table1 == b.ID1Table2 && a.ID2Table1 == b.ID2Table2
select new {a.ID1Table1, a.ID2Table1, a.Value1Table1, b.ID3Table2, b.Value1Table2}


Eğer yapılan join işlemlerinde field isimleri birbirini eşit değilse "The type arguments cannot be inferred from the query..." alabilirsiniz. Böyle bir durumda "new" komutu ile oluşturduğunuz class alanlarına ortak isimler vermelisiniz.

join inventory in Models.Inventories on new
{
	Supplier = equivalency.EquivalencySupplier,
	Part = equivalency.EquivalencyPart
} equals new
{
	Supplier = inventory.Supplier,
	Part = inventory.Part
}

 

İyi çalışmalar.



Entity Framework'e Giriş

clock Eylül 3, 2014 11:47 by author OzgurOzvaris

Merhaba Arkadaşlar,

Entity Framework (EF) ile ilgili pek yazı kaleme almadım. Aslında bu tarafta hatırı sayılır miktarda Entitiy Framework tecrübesi birikti. Sizlerle ara ara bunlarıda paylaşmaya çalşacağım. Aslında bu yazıda "Entity Framework Join" konusuna deyinecektim ancak bu vesile ile biraz Entity Frame work'un genel konularına değineyim.

Entity Framework emsalleri ile karşılaştırılınca gerçekten bambaşka bir dünya. Bazen insanı çılgına çevirecek kadar zor, bazende ya bunuda mı yapıyor helal olsun bu adamlara diyecek kadar tatminkar. Bazende bunu nasıl hâlâ eklememişler diyecek kadar sizi üzen, sürekli size karma karışık duygular yaşatan, sürekli gelişen bir sistem. Zaten 6.0 versiyonunu görmesi ve hala hızla gelişmeside buna en basit örnek.

Ayrıca hâlâ güçlü bir yazılımının data katmanı EF ile geliştirilebilir mi diye piyasada ciddi endişeler var. Kabul elmek gerek ki "SQL" database ile kurulan çok ciddi bir iletişim yöntemi ve belkide EF hiçbir zaman onun kadar güçlü olamayacak. Ancak sql ve EF'ü kıyaslamak bana adil gelmiyor. EF gücünü sistemlerinden (Code First, Design First, Database First, POCO vb. ) alıyor. EF adeta kıyas edersek yazı dünyasındaki Word uygulaması yolun da gidiyor, sql ise database dünyasının karakalemi gibi. Sql'de varyasyonlar bir hayli çoğalmış durumda tabi ki EF'de varyasyonlar o kadar çok değil.

Entitiy Framework'te doğru synax ve doğru sql çıktısı çok önemli. Gerçekten çok güçlü bir yapı. Ancak sadece yazdım bitti diyemiyorsunuz. Bir şekilde alışana kadar sql profiler'dan ve ya başka şekillerde EF'ün efektif SQL cümleleri üretip üretmediğini kontrol etmeniz gerekiyor.

Aslında bu makaleye "Entity Framework Join" demiştim ancak yazı başka yöne doğru gidince başlığı şimdiki başığa çevirdim.

Birazdan "Entity Framework Join" makalemide yayınlayacağım inşallah.

Herkese iyi çalışmalalar.



Hakkımızda  AboneOl 

Blog Yayınımıza Hoşgeldiniz.

Month List

RecentPosts

Sign In