C# 将两个列表与LINQ扩展关联

C# 将两个列表与LINQ扩展关联,c#,asp.net-mvc,linq,lambda,C#,Asp.net Mvc,Linq,Lambda,我有两个不同对象的列表,一个来自第三方API,另一个来自我的数据库——我正试图将这两个对象作为一种关系链接起来。理想情况下,DBML如何为具有外键的表创建关系(Customer.Orders)的效果类似 来自第三方: class ApiObject { public string ID { get; set; } public string Title { get; set; } public DateTime CreatedDate { get; set; }

我有两个不同对象的列表,一个来自第三方API,另一个来自我的数据库——我正试图将这两个对象作为一种关系链接起来。理想情况下,DBML如何为具有外键的表创建关系(
Customer.Orders
)的效果类似

来自第三方:

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==dblobject.apid

我不想合并这些对象,也不想将它们合并到某个匿名对象中(并明确列出30多个属性),而是想使
dblobject
成为
ApiObject
的链接属性。i、 e:可寻址为:
apiObject.DbmlObjects.First().OtherString
或理想情况下的
apiObject.DbmlObject.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.
List apiObjects=\u thirdParty.GetObjects();
DbmlDataContext模型=新的DbmlDataContext();
List dbmlObjects=model.GetAllDbmlObjects();
//在这里把它们联系起来
foreach(apiObjects中的var apiObject)
Write(apiObject.DbmlObject.OtherString)
//注意:理想情况下,这个foreach循环不应该在每次迭代中进行DBML查询,而应该只进行上面的单个GetAllDbmlObjects查询。

听起来像是一个
加入

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
,可以基于
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,…),而且你肯定会想缓存反射结果,这样你就不需要每次遍历类型了-反射(相对)比较慢。

它们之间有什么关系,通过
apid
?@TimSchmelter by
ApiObject.ID==dblobject.apid
,这是我的猜测。是的,对不起,假设它是直观的,但我会明确说明如果您希望它像这样可寻址,我会建议使用添加属性DmlObject的ApiObject类的新子类。此类的构造函数将采用现有的ApiObject和现有的DmlObject。然后,您可以将该类当作ApiObject的实例来使用。这样,您就可以得到一个对象:
{ApiObject api,DbmlObject dbml}
,而不是
NewObject
的对象。。这就是带有额外子属性的
ApiObject
@arserbin3的
ApiObject
:然后您需要创建第三个类,其属性为
ApiObject
+
OtherString
,您可以在联接的
选择中初始化它。
您可以在ApiObject类中声明
dblobject
,还是必须保留?这不是意味着明确地说:
选择新的ApiObjectWithDbml{prop1,prop2,prop3,…propN,dbmlObject}
?以及使用DBML{prop1,…propN}
创建一个
类apiObject。如果他想将其用作apiObject,那么在这种情况下,apiObject的继承性会更好。