2013-02-27 40 views
1

我一直在試圖構建兩個不同的數據庫中的兩個模型可能看起來像一個奇怪的加入方法,你可以查詢第一個,然後返回ID的小列表進行搜索另一個分貝。一切工作正常吧一個或兩個東西,我不能做Id列表子查詢使用lambda函數,我有Id選擇器功能,鏈接了通用但在where子句現在將工作,因爲我不知道誰鏈接源類型對象爲Id的傳遞函數,所以.Where(TSource => idlist.Contains(Idselector)示例代碼由於List.Conatins代碼而低於最大值。如果有人可以幫助將不勝感激,因爲我stook從SourceB獲取任何元素在SourceA中的ID

public static Foo JoinTwoModels<T1,T2>(
      DbSet Dbs1, 
      DbSet Dbs2, 
      Expression<Func<T1, object>> Id1, 
      Expression<Func<T1, dynamic>> Selector1, 
      Expression<Func<T1, bool>> Search1, 
      Expression<Func<T2, object>> Id2, 
      Expression<Func<T2, dynamic>> Selector2) 
     { 
      var Output1 = Queryable.OfType<T1>(Dbs1); 

      var Output2 = Queryable.OfType<T2>(Dbs2); 

      List<dynamic> Result1 = Output1.Where(Search1).Select(Selector1).ToList(); 

      List<object> idList = new List<object>(); 

      PropertyInfo p1 = Result1[0].GetType().GetProperty("Id"); 

      foreach (var o1 in Result1) 
      { 
       idList.Add(p1.GetValue(o1)); 
      } 

      //Query result entries into db 
      List<T2> Result2 = Output2.Where(idlist.contains(Id2)).ToList(); 

回答

0

怎麼是這樣的:

public class Foo 
{ 
    public int Context; 
    public string Data; 
} 

public class Bar 
{ 
    public int Context; 
    public string Data; 
} 

public static IEnumerable<TOutput> JoinTwoModels<T1, T2, TIdent, TOutput>(
    IEnumerable<T1> sourceA, 
    IEnumerable<T2> sourceB, 
    Func<T1, TIdent> idSelectorA, 
    Func<T2, TIdent> idSelectorB, 
    Func<T1, TOutput> selectorA, 
    Func<T2, TOutput> selectorB) 
{ 

    var quearyA = sourceA 
      .Select(x => new {Value = selectorA(x),Id = idSelectorA(x)}); 

    var quearyB = sourceB 
      .Select(y => new {Value = selectorB(y),Id = idSelectorB(y)}) 
      .Where(y => quearyA.Select(x => x.Id).Contains(y.Id)) 
      .Select(y => y.Value); 


    return quearyA.Select(x => x.Value).Concat(quearyB); 
} 

private static void Main(string[] args) 
{ 
    var sourceA = new List<Foo>() {new Foo() {Context = 2, Data = "I'm a Foo"}}; 
    var sourceB = new List<Bar>() {new Bar() {Context = 2, Data = "I'm a Bar"}}; 

    var Output1 = sourceA.AsQueryable(); 
    var Output2 = sourceB.AsQueryable(); 

    var results = JoinTwoModels(
     Output1, 
     Output2, 
     (Func<Foo, int>) (x => x.Context), 
     (Func<Bar, int>) (x => x.Context), 
     (Func<Foo, string>) (x => x.Data), 
     (Func<Bar, string>) (x => x.Data)); 

    foreach (var item in results) 
     Console.WriteLine(item); 
} 

你想不太清楚是什麼;所以上面我選擇了Source-A(類型爲Foo)和Source-B(類型爲Bar)共享一個公共Context(id)的所有項目,並以轉換後的公共類型返回它們。

可以簡化下來,如果你只是想從B值,到:

var quearyA = sourceA.Select(idSelectorA); 

var quearyB = sourceB 
     .Select(y => new {Value = selectorB(y),Id = idSelectorB(y)}) 
     .Where(y => quearyA.Select(x => x).Contains(y.Id)) 
     .Select(y => y.Value); 

return quearyB; 
+0

感謝您的回覆,並幫助大衛,你是正確的,我想加入兩個結果一起的ID,但我想靈活地選擇多個/不同的領域,每次因此動態函數返回,我只是中間所以不確定,但是你的固定到類固定值/ id屬性,或者這是動態的數字字段返回?這似乎是LINQ到對象的IEnumberable查詢,這將工作與IQueryable到DB一樣嗎?再次感謝 – Gerard 2013-02-27 18:42:00

+0

首先,IEnumerable將不會運行,直到迭代結果爲止;所以我認爲你可以安全地在IQueryable之上運行IEnumerables(儘管我從未嘗試過)。至於動態;動態將編譯時的問題轉移到運行時。我會盡量避免它,並強烈鍵入...... Foo,T1,T2和TOutput可以是任何東西。但我想你的數據庫將有兩列,ID和VALUE,並且VALUE的類型在行與行之間不會改變。 – 2013-02-27 18:48:00

+0

也不要混淆兩個問題;去抓取匹配ID的值;這將作爲IEnumerable返回...將其轉換爲Query並在其上運行您的數據字段選擇。即您可以將T1和T2作爲IQueryable。 etc ... – 2013-02-27 19:23:11