LINQ projeksiyonlarında anonim türlerin zorluğu

Womanne

Member
Microsoft’un LINQ genel sorgu dilini kullanırken karşılaşılan temel zorluklardan biri, sonuç kümesini yalnızca öznitelikler veya sütunlar açısından sınırlandırdığınızda ortaya çıkan anonim sınıflardır. Anonim bir tür yalnızca yerel bir değişken olarak kullanılabilir, ancak yöntemlerden dönüş değeri olarak kullanılamaz.

Duyuru



LINQ’daki standart bir sorgu, SELECT bölümündeki yürütme değişkenine başvurur. Bu, SQL’deki “SELECT *” ile eşdeğerdir.

Numaralandırılabilir sonuç = kümedeki x’ten itibaren… x’i seçin;

Özellikle büyük veritabanı tablolarını sorgularken tüm sütunların seçilmesi doğru bir davranış değildir. LINQ daha sonra projeksiyon adı verilen bir yöntemi kullanarak SELECT kısmındaki hedef nesneleri daraltmayı planlıyor. Bu, anonim olarak adlandırılan bir tür oluşturur. Anonim tür, çeviri sırasında derleyicinin kendisi tarafından oluşturulan ve derleyici tarafından da isimlendirilen bir sınıftır. Giriş zamanında tür adı bilinmediğinden, C# ve Visual Basic dilleri özel sözdizimsel formlar sunar (As olmadan var veya Dim):

C#: var result = x’ten sete burada… select new { xa, xb, xc };

VB: Sonuç Dim = kümedeki x’ten itibaren… { xa, xb, xc } ile yeniyi seçin;

En büyük zorluk, anonim türlerin yalnızca yerel değişkenler olarak kullanılabilmesidir. Anonim türler, örnek veya sınıf üyeleri için veya dönüş değerleri için kullanılamaz. Bu ciddi sınırlama birçok kullanıcı tarafından eleştiriliyor ancak Microsoft, C# 4.0’da bunu değiştirmeyeceğini zaten açıklamıştı. Ne yazık ki, LINQ tarafından sağlanan cast operatörünü kullanarak anonim bir türü geliştirici tanımlı bir sınıfa dönüştürmek bile mümkün değildir.

Daha sonra, bir projeksiyonun sonucunun diğer yöntemlere aktarılması mümkün olmadığında, LINQ projeksiyonlarının kapsülleme ve katmanlı geliştirme ile nasıl uzlaştırılacağı sorusu ortaya çıkar.

Aşağıdaki seçenekler mevcuttur:

1. System.Object temel türüyle anonim nesneleri döndürmek ve çağıran program kodunda aynı şekilde oluşturulmuş anonim bir tür kullanarak arayandaki türü dönüştürmek mümkündür, ancak çok rahatsız edicidir (örneğe bakın)

2. LINQ’dan SQL’e kullanıyorsanız, veri bağlamında yazılan ve veritabanındaki tablonun yalnızca bir alt kümesini temsil eden kendi iş nesnesi sınıflarınızı oluşturabilirsiniz. Bu, taramaların artık gerekli olmadığı anlamına gelir. Çalışma zamanı hızı hızlıdır ancak birçok projeksiyona ihtiyaç duyulduğunda kendi iş nesnesi sınıflarınızı oluşturmak çok can sıkıcıdır.

3. LINQ’dan SQL’e kullanırken sorgu dili olarak LINQ yerine SQL’i kullanabilirsiniz. Bir iş nesnesi sınıfını kısmen doldurabilirsiniz. Microsoft’un bu kısmi dolguyu SQL için etkinleştirmesi ama LINQ için etkinleştirmemesi garip. IEnumerable Fluege5 = DB.ExecuteQuery(“Tablodan xa, xbxc’yi x olarak seçin, burada …”); Çözüm başarılı ancak LINQ sözdizimi olmadan yapmak acı verici.

4. Giriş kümesinin her öğesi için hedef sınıfın bir örneğini oluşturan ve .NET yansımasını kullanarak özniteliği yeni örneğe kopyalayan IEnumerable arabirimi için bir uzantı yöntemi olarak kendi dönüştürme operatörünüzü yazabilirsiniz. Daha sonra çağrı çok zarif bir şekilde yazılabilir: IEnumerable Result2 = Result.Convert(). Uygun program kodunu aşağıda bulabilirsiniz

Kod:
 . Bu çözümün dezavantajı .NET yansımasının kullanılmasından kaynaklanan hız kaybıdır. Ayrıca kopyalanan nesnelerin veri bağlamından ayrıldığına ve Context.Table.AttachAll(Quantity, false) kullanılarak ona tekrar eklenmesi gerektiğine de dikkat edilmelidir. Diğer fikirlere açığız!


Convert() uzantı yönteminin listelenmesi

///
 
/// LINQ projeksiyonları için uzantı

/// (C) www.IT-Visions.de Holger Schwichtenberg 2008

///

dahili statik sınıf WWWingsProjectionExtensions

{

///
 
/// Bir türden (anonim) bir kümeyi başka bir türe dönüştürme

/// aynı isimdeki özellikleri eşliyoruz

///

genel statik IEnumerable Dönüştürmek(bu IEnumerable’ı ayarlar, System.Data.Linq.ITable tablosu)
 
burada T : yeni()

{

// Yeni miktar

Liste Sonuç = yeni Liste();
 
// Dahil edilen nesneleri çoğaltın

foreach(nesne veya kümede)

{

T e = CopyIn(veya);
 
Sonuç.Add(e);

}

// Yeni kümeyi veri bağlamına ekler

Table.AttachAll(Sonuç, false);

Sonuç döndür;

}

///
 
/// Aynı isimdeki özelliği başka bir nesneye kopyalar

///

genel statik T CopyTo(itiraz eden)
 
burada T : yeni()

{

Ta = yeni T();

CopyA’yı döndür(başlangıçtan itibaren);
 
}

///
 
/// Aynı isimdeki özelliği başka bir nesneye kopyalar

///

genel statik T CopyTo(nesneden, T’ye)
 
burada T : yeni()

{

FromType = from.GetType() yazın;

ToType = to.GetType() yazın;

// Alanları kopyalıyoruz

foreach(FieldInfo f, FromType.GetFields())

{

FieldInfo t = ToType.GetField(f.Name);

if (t!= null)

{

t.SetValue(to, f.GetValue(from));

}

}

//Özellikleri kopyala

foreach(PropertyInfo f, FromType.GetProperties())[] {[0]nesne

Boş = yeni nesne

;

PropertyInfo t = ToType.GetProperty(f.Name);

if (t!= null)

{

//Console.WriteLine(f.GetValue(from, Empty));

t.SetValue(a, f.GetValue(from, Empty), Empty);

}

}

Geri vermek;

}



}



()Haberin Sonu
 
Üst