2012-07-17 56 views
1

我有兩個不同的對象列表,一個來自第三方API,另一個來自我的數據庫 - 我試圖將這兩個關係鏈接起來。理想情況下,DBML與外鍵表(Customer.Orders)創建關係的效果相似。關聯兩個列表LINQ擴展

來自第三方:

class ApiObject { 
    public string ID { get; set; } 
    public string Title { get; set; } 
    public DateTime CreatedDate { get; set; } 
    ... 30 other properties ... 
} 

從我的數據庫:

class DbmlObject { 
    public int ID { get; set; } 
    public string ApiID { get; set; } 
    public string OtherString { get; set; } 
} 

它們通過ApiObject.ID == DbmlObject.ApiID

有關我不想合併這些,不把它們加入到一些匿名對象(並明確列出30多個屬性) - 而是使DbmlObject成爲​​的鏈接屬性。即:可尋址爲: apiObject.DbmlObjects.First().OtherString或理想情況下​​,因爲它是1對1的關係。

在控制器:

List<ApiObject> apiObjects = _thirdParty.GetObjects(); 

DbmlDataContext model = new DbmlDataContext(); 
List<DbmlObject> dbmlObjects = model.GetAllDbmlObjects(); 

// relate them here 

foreach (var apiObject in apiObjects) 
    Console.Write(apiObject.DbmlObject.OtherString) 
// NOTE: ideally this foreach loop should not make a DBML query on each iteration, just the single GetAllDbmlObjects query above. 
+0

它們是如何通過「ApiID」關聯的? – 2012-07-17 20:25:55

+0

@TimSchmelter by'ApiObject.ID == DbmlObject.ApiID',是我的猜測。 – 2012-07-17 20:27:11

+0

是的,對不起,以爲它很直觀,但我會明確 – arserbin3 2012-07-17 20:28:36

回答

2

這聽起來像一個join

var combined = from api in apiObjects 
       join dbml in dbmlObjects on api.ID equals dbml.ApiID 
       select new { api, dbml } 

爲了 「中的」 APIObject中得到DbmlObject,你要麼需要繼承的APIObject,構建一個新的該類包括Dbml屬性,創建一個全新的類來返回。如果你需要靜態打字,這是最好的,你可以做 - 當然你可以(錯誤)使用dynamic來得到你想要的。

在這種情況下,你提到(在註釋中)ApiObject類來自第三方庫,你不能改變 - 在這種情況下,我可能會選擇創建一個新的類型,它需要兩個實例對象在構造函數中,並公開你需要的屬性 - 裝飾器。是的,它看起來像很多代碼,但並不複雜,好的工具會爲你自動生成它 - 並且你得到的代碼所需的類是簡潔的。

如果您想要進一步返回IEnumerable<dynamic>,您可以基於DynamicObject構建一個「組合動態」對象,然後響應ApiObject和DbmlObject的所有屬性 - 或者僅將DbmlObject添加爲屬性。我並不是說這是正確的路,它取決於你需要什麼 - 記住你正在失去類型安全。這裏有一個簡單的例子:

void Main() 
{ 
    dynamic dyn = new CombiningDynamic(new Foo { X = 3 }, new Bar { Y = 42 }); 
    Console.WriteLine(dyn.X); 
    Console.WriteLine(dyn.Y); 
} 

public class Foo 
{ 
    public int X {get;set;} 
} 

public class Bar 
{ 
    public int Y { get;set;} 
} 

public class CombiningDynamic : DynamicObject 
{ 
    private object [] innerObjects; 


    public CombiningDynamic(params object [] innerObjects) 
    { 
     this.innerObjects = innerObjects; 

    } 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     foreach(var instance in innerObjects) 
     { 
      Type t = instance.GetType(); 
      PropertyInfo prop = t.GetProperty(binder.Name); 
      if (prop != null && prop.CanRead) 
      { 
       result = prop.GetValue(instance, null); 
       return true; 
      } 
     } 
     result = null; 
     return false; 
    } 
} 

請記住,這是示例代碼。如果你真的這樣做,你可能會想要重寫一些更多的方法(TrySetMember,...),並且你最明確地想要緩存反射結果,所以你不需要每次都走這些類型 - 反射(相對)緩慢。

+0

這留給你一個對象: '{ApiObject api,DbmlObject dbml}'而不是'NewObject'的對象..這就是'ApiObject'帶有一個額外的子屬性'DbmlObject' – arserbin3 2012-07-17 20:31:39

+0

@ arserbin3:那麼你需要用'ApiObject' +'OtherString'屬性創建第三個類,你可以在'select連接中初始化'。 – 2012-07-17 20:35:02

+0

你可以在ApiObject類中聲明'DbmlObject',還是需要保留? – driis 2012-07-17 20:35:06