2008-12-23 32 views
9

Visual Studio 2008 ile örnek olarak yayınlanan dinamik LINQ uzantı yöntemlerinin bir kütüphanesi vardı. Birleştirme yöntemi ile genişletmek istiyorum. Aşağıdaki kod, çalışma zamanında bir parametre eşleşme istisnasıyla başarısız oluyor. Sorun nerede?Dinamik LINQ birleştirme uzantısı yöntemi oluşturma

public static IQueryable Join(this IQueryable outer, IEnumerable inner, 
           string outerSelector, string innerSelector, string resultsSelector, 
           params object[] values) 
{ 
    if (inner == null) 
     throw new ArgumentNullException("inner"); 
    if (outerSelector == null) 
     throw new ArgumentNullException("outerSelector"); 
    if (innerSelector == null) 
     throw new ArgumentNullException("innerSelector"); 
    if (resultsSelector == null) 
     throw new ArgumentNullException("resultsSelctor"); 

    LambdaExpression outerSelectorLambda = 
     DynamicExpression.ParseLambda(outer.ElementType, null, 
             outerSelector, values); 
    LambdaExpression innerSelectorLambda = 
     DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, 
             null, innerSelector, values); 

    ParameterExpression[] parameters = new ParameterExpression[] { 
     Expression.Parameter(outer.ElementType, "outer"), 
     Expression.Parameter(inner.AsQueryable().ElementType, 
     "inner") 
    }; 
    LambdaExpression resultsSelectorLambda = 
     DynamicExpression.ParseLambda(parameters, null, 
             resultsSelector, values); 

    return outer.Provider.CreateQuery(
     Expression.Call(
      typeof(Queryable), "Join", new Type[] { 
       outer.ElementType, 
       inner.AsQueryable().ElementType, 
       outerSelectorLambda.Body.Type, 
       innerSelectorLambda.Body.Type, 
       resultsSelectorLambda.Body.Type 
      }, 
      outer.Expression, inner.AsQueryable().Expression, 
      Expression.Quote(outerSelectorLambda), 
      Expression.Quote(innerSelectorLambda), 
      Expression.Quote(resultsSelectorLambda)) 
     ); 
} 
+0

Eğer hata mesajını tam yapıştırmak olabilir aşağıdaki şekilde yapılabilir? – Perpetualcoder

+0

Birleşiminizi kullanarak bir örnek gönderir misiniz? Onu kullanmak isterdim, ama ben LINQ'da böyle bir yeşim var. Teşekkürler. – joe

cevap

19

Şimdi kendim onardım. CreateQuery (...) çağrısına çok fazla parametre geçiren bir öğrenci hatasıydı. Dinamik birleştirme uzantısı yöntemi için aşağıdaki kodu DynamicQueryable sınıfındaki Dynamic.cs dosyasına yapıştırın. DynamicQuery örnek projesinin kaynağını http://code.msdn.microsoft.com/csharpsamples adresinde bulabilirsiniz.
Keyfini çıkarın.

public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) 
    { 
     if (inner == null) throw new ArgumentNullException("inner"); 
     if (outerSelector == null) throw new ArgumentNullException("outerSelector"); 
     if (innerSelector == null) throw new ArgumentNullException("innerSelector"); 
     if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor"); 

     LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values); 
     LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values); 

     ParameterExpression[] parameters = new ParameterExpression[] { 
      Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; 
     LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values); 

     return outer.Provider.CreateQuery(
      Expression.Call(
       typeof(Queryable), "Join", 
       new Type[] {outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, 
       outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda))); 
    } 


    //The generic overload. 
    public static IQueryable<T> Join<T>(this IQueryable<T> outer, IEnumerable<T> inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) 
    { 
     return (IQueryable<T>)Join((IQueryable)outer, (IEnumerable)inner, outerSelector, innerSelector, resultsSelector, values); 
    } 
+0

Kullanım örneği burada: http://stackoverflow.com/questions/5996403/counting-percent-of-rows-with-category-out-of-total-number-of-rows-using-dynamic/6047324#6047324 – alpav

+0

Bu kodun basit kullanımı şu şekildedir: 'var sonuç = myDbContext.Person .Join (myDbContext.Roles," new (firstKey olarak adlandırma, secondKey olarak SomeOtherId) "," new (FirstKey olarak PersonId, secondKey olarak AlternativeId) " , "yeni (r olarak dış, p olarak"); 'Eğer birden fazla sütun üzerinde birleştirilirse," aynı şekilde adlandırılmamışsa "ya da bir hata ortaya çıkarsa," [somekey] "olarak bize ihtiyacınız olduğunu unutmayın. Ayrıca sonuç seçicisinde "dış" ve "iç" anahtar sözcüklerini kullanırsınız. Bu soruya cevap vermeyen – user2945722

1

Birden çok sütunda bir birleştirmeyi gösteren örnek kod aşağıda verilmiştir. Bir veri tabanını ve veri kümelerini kullanarak, her zaman alanlara dizinleyici aracılığıyla erişmeniz gerekir.

DataTable t1 = new DataTable(); 
    t1.Columns.Add("FundId", typeof(int)); 
    t1.Columns.Add("Date", typeof(DateTime)); 
    t1.Columns.Add("CodeA", typeof(string)); 
    t1.Rows.Add(1, new DateTime(2010, 01, 01), "A1"); 
    t1.Rows.Add(2, new DateTime(2010, 01, 01), "A2"); 
    t1.Rows.Add(3, new DateTime(2010, 01, 01), "A3"); 

    DataTable t2 = new DataTable(); 
    t2.Columns.Add("FundId", typeof(int)); 
    t2.Columns.Add("Date", typeof(DateTime)); 
    t2.Columns.Add("CodeB", typeof(string)); 
    t2.Rows.Add(1, new DateTime(2010, 01, 01), "B1"); 
    t2.Rows.Add(2, new DateTime(2010, 01, 01), "B2"); 
    t2.Rows.Add(3, new DateTime(2010, 01, 01), "B3"); 

    IQueryable outerTable = t1.AsEnumerable().AsQueryable(); 
    IEnumerable innerTable = t2.AsEnumerable(); 

    var query = outerTable.Join 
    (
     innerTable, 
     "new(get_Item(0) as FundId, get_Item(1) as Date)", 
     "new(get_Item(0) as FundId, get_Item(1) as Date)", 
     "new(outer.get_Item(0) as FundId, outer.get_Item(2) as CodeA, inner.get_Item(2) as CodeB)" 
    ); 
+0

. Burada Linq tarafından sağlanan birleştirme yöntemini kullanın, bu soru - Linq tarafından henüz sağlanmadığı için bu yöntemi yaratmayla ilgiliydi. – psycho

2

Sen System.Linq.Dynamic.Core ait Nuget paketini yükleyebilirsiniz - https://github.com/StefH/System.Linq.Dynamic.Core

Bu çeşitli diğer yardımcı yöntemleri ile birlikte hayata katılmak yöntemi vardır. katılmak sonucunu erişmek için anahtar kelimeler basit yapabilirsiniz Bu kütüphaneyi kullanarak

sonuç seçicisi outer ve inner yol myContext.TableA.Join(myContext.TableB,'Id','TableAId','outer',null)

aşağıdaki katılmak bulunmaktadır. birden çok özellik ve/veya birden fazla özelliklere sahip bir sonucu seçtikten sahip bir anahtar kullanarak

myContext.TableA.Join(myContext.TableB,'new (Id as key1,Code as key2)','new (TableAId as key1,AnotherCol as key2)','new(outer.Id,inner.Desc)',null)

İlgili konular