2011-08-11 54 views
0

我有一個方法與此類似,其循環通過一組數據,並使用第一對象的值來查找一個對象中的第二組數據:動態功能/ lambda表達式

private void someMethod(IQueryable<RemoteUser> source, IQueryable<LocalUser> targetData) { 

    // Loop all records in source data 
    foreach(var u in source) { 

     // Get keyvalue from source data and use it to find the matching record in targetData 
     var keyValue = u.id; 
     var object = from data.Where(o => o.id == keyValue).FirstOrDefault();  
     ... 
    } 

} 

我想,使其更重用通過傳遞函數功能,或者使用一些其它類型的拉姆達的,然後方法轉換的東西,我可以在一個通用的方式使用,即:

private void someMethod<SourceT, TargetT>(IQueryable<SourceT> source, IQueryable<TargetT> targetData) { 
    .... 
} 

我是什麼不完全確定的是我可以如何構建一個Func /謂詞/等,並將其傳遞給方法。請記住,所有SourceT屬性中的「id」屬性都不相同。

爲了進一步解釋,我想的東西在那裏我可以做到這一點:

的someMethod(RemoteUsers,LocalUsers,something here to say 'find the user using the userId property');

someMethod(RemoteProducts,LocalProducts,something here to say 'find the user using the productId property');

回答

1

這裏是最基本的實現你的someMethod例行:

private void someMethod<S, T, P>(
    IQueryable<S> source, 
    IQueryable<T> target, 
    Func<S, P> sourceSelector, 
    Func<T, P> targetSelector) 
{ 
    foreach(var s in source) 
    { 
     var sp = sourceSelector(s); 
     var @object = target 
      .Where(t => targetSelector(t).Equals(sp)).FirstOrDefault();  
     //... 
    } 
} 

這種實現保持你原來的代碼結構,但這是有代價的。您正在針對您的數據庫實際執行source.Count() * target.Count()查詢。使用IQueryable<>時,您需要放棄使用foreach。實際上,只要你開始用foreach編寫代碼,你需要問問自己,你是否可以使用LINQ查詢來構建和過濾數據,並使循環只執行「最簡單」的任務。

下面是如何使該方法更好地工作:

private void someMethod2<S, T, P>(
    IQueryable<S> source, 
    IQueryable<T> target, 
    Expression<Func<S, P>> sourceSelector, 
    Expression<Func<T, P>> targetSelector) 
{ 
    var query = source 
     .GroupJoin(
      target, 
      sourceSelector, 
      targetSelector, 
      (s, ts) => ts.FirstOrDefault()); 

    foreach(var @object in query) 
    { 
     //... 
    } 
} 

注意使用Expression<Func<,>>而不僅僅是Func<,>。還請注意方法調用GroupJoin

+0

我的源和目標IQueryable數據不是來自同一個數據源,事實上,它甚至不是數據庫 - 它來自Web服務。如何調用someMethod外觀(P代表什麼?) – bugfixr

+0

@Chu - 由於它們來自不同的源,因此不需要使用'IQueryable <>'和表達式。我仍然使用'GroupJoin'方法並儘可能保持你的'foreach'儘可能輕。 'P'只是你加入的屬性(或者更確切地說它們的類型)。 – Enigmativity

+0

感謝您的澄清。只是爲了理解選擇器部分,我將什麼傳遞給someMethod作爲我的'sourceSelector'? – bugfixr