2016-07-05 19 views
5

Arkaplan

I veya belirli bir tarihten önce oluşturulan kayıtları aşağı sonuçları filtreleyen bir .Include inşa etmek gerekiyor

. Orijinal LINQ deyimindeki nesnelerin türlerini bilmeyeceğim ve onları bulmaya çalışacağım (bir sürü halka aracılığıyla, ama bu işe yarıyor). Orijinal linq yazarken yani bir geliştirici bu ilişkileri yazın vermez (dinamik Dahil, Build ile nerede Filtre

  A -> Ac 
     /\ 
    Bc <- B \ 
    / \ 
Cc <- C  D -> Dc 

Nesneler Ac, Bc, Cc ve Dc tüm dinamik olarak bulunurlar:

böyle nesnelerin bir grafik var Beyan). Bunlar daha sonra bir IQueryable ifadesine eklenmeli ve değerleri yalnızca belirli bir DateTime'a döndürmelidir.

Kod So Far

Bir lambda oluşturur ve tarihleri ​​karşılaştıran bir işlevi oluşturmak çalıştı. Şimdiye kadar, eğer orijinal sorgu A.Include(x => x.B).Include(x => x.B.Select(y => y.C) ise, "A.B.Bc" dizesini oluşturabilirim, böylece A, B ve Bc türlerini ve bunların ilişkilerini biliyorum.

private static IQueryable<T> FilterChangeTrackerToDate<T>(this IQueryable<T> query, string includeString, DateTime targetDateTime) 
{ 
    var param = Expression.Parameter(typeof(T), "x"); 

    var prop = Expression.Property(param, includeString + ".CreatedUtc"); 

    var dateConst = Expression.Constant(targetDateTime); 

    var compare = Expression.LessThanOrEqual(prop, dateConst); 

    var lambda = Expression.Lambda<Func<T, bool>>(compare, param); 

    return query.Where(lambda); 
} 

konu "A.B.Bc.CreatedUtc" tarih özelliği yüklemek için doğru yol değildir, çünkü yukarıdaki kod çöküyor olmasıdır - Ben .Select ifadeleri ile bu hareket etmesi gerekli. Her iki amacıyla

Sorun

yük kayıtları ve onları, ben dinamik olarak (minnetle, miras dayalı statiktir) Ben gereken değerleri çekme yönündeki bir .Select inşa etmek gerekfiltre ve bu değerleri anonim bir türe yerleştirin, daha sonra bir .Where() ile filtrelenebilir. Bunların hepsinin asgari jenerikle yapılması gerekiyor, çünkü derleme zamanı türlerini doğrulamamak için kullanmam gerekiyor ve ben de bunları işe almak için yansımayı kötüye kullanmak zorundayım.

Esasen, ben bu oluşturmanız gerekir:

.Select(x => new 
{ 
    Bc = x.B.Select(z => z.Bc.Select(y => y.CreatedUtc).Where(q => q > DateTime.UtcNow)), 
    A= x 
}) 

dinamik, yuvalama herhangi bir düzeyi için, dize "A.B.Bc" seçeneğini kullanarak. sadece üst düzey değerlerini seçer ve görünmüyor dinamik bir seçin oluşturma hakkında LINQ To Entities Include + Where Method

Bu mesaj görüşmelerini ama: Ben EF filtrelemek nasıl gördüğünü burasıdır

Kaynaklar

yöntemini içerir How to create LINQ Expression Tree to select an anonymous type

Dinamik Linq System.Linq kullanma

: gibi benim problem için gerekli parçaların kalanını inşa edebilirsiniz.Dinamik kütüphane, ben Bc kapalı CreatedUtc değerini erişmeye çalıştık:

includeString = "B.Bc"
query = (IQueryable<T>) query.Select(includeString + ".CreatedUtc"); 

ama bu bana ait bir istisna verir:

Exception thrown: 'System.Linq.Dynamic.ParseException' in System.Linq.Dynamic.dll 

Additional information: No property or field 'Bc' exists in type 'List`1' 

cevap

2

Ben System.Linq.Dynamic neye ihtiyacınız olduğuna inanıyoruz. Başlangıçta Microsoft'tan ScottGu tarafından yazılmış bir kütüphane, ve böyle dizesinden LINQ sorgu oluşturmanızı sağlar:

IQueryable nestedQuery = query.Select("B.Bc.CreatedUtc"); 

sorgu IQueryable<A> olduğu.

Bu kitaplığın çeşitli çatalları var. here'dan başlayabilirsiniz. Sorgulama dili belgesinde here bulunur. Ayrıca here bazı ek işlevlere sahip bir sürüm ve here dotnet.core sürümüdür.

UPD1: This kütüphane SelectMany uzatma yöntemi yoksun ama this birine sahiptir. aşağıdakileri yapabilirsiniz ikincisi kütüphane ile So: Ben dize ` "B.Bc.CreatedUtc"` eklediğinizde

query.SelectMany("B").SelectMany("Bc").Select("CreatedUtc"); 
+0

, bu hatayı alıyorum: 'Ek bilgi: Hiçbir tesisin veya alanın 'Bc' türü var 'List'1''. İç içe geçmiş grafikleri doğru şekilde incelemek gibi görünmüyor mu? – Max

+0

Kodunuzun daha fazlasını burada gösterebiliyor musunuz? –

+0

Ana sayfamı güncelledim. – Max