C# 将两个列表与LINQ扩展关联
我有两个不同对象的列表,一个来自第三方API,另一个来自我的数据库——我正试图将这两个对象作为一种关系链接起来。理想情况下,DBML如何为具有外键的表创建关系(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; }
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 byApiObject.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的继承性会更好。