使用 LINQ 查询和创建具有一对多关系的对象
本文关键字:一对多 关系 对象 LINQ 查询 创建 使用 | 更新日期: 2024-10-30 04:56:13
在数据库中,我有两个具有一对多关系的表:
orders suborders
----------- -----------
id id
name order_id
name
我想查询这些表并最终得到一个订单对象列表,每个对象都包含一个子订单对象列表(或空列表)。我还想在单个数据库查询中执行此操作,以便它性能良好。
在传统的SQL查询领域,我会做类似的事情(原谅伪代码):
rs = "select o.id, o.name, so.id, so.name from orders o left join suborders so on o.id = so.order_id order by o.id"
orders = new List<Order>
order = null
foreach (row in rs) {
if (order == null || row.get(o.id) != order.id) {
order = new Order(row.get(o.id), row.get(o.name), new List<Suborders>)
orders.add(order)
}
if (row.get(so.id) != null) {
order.suborders.add(new Suborder(row.get(so.id) row.get(so.name))
}
}
有没有办法使用 LINQ 到实体来获取相同的结果对象结构?请注意,我想从查询中获取新对象,而不是实体框架生成的对象。
以下内容让我接近,但抛出异常:"LINQ to Entities 无法识别该方法..."
var orders =
(from o in Context.orders
join so in Context.suborders on o.id equals so.order_id into gj
select new Order
{
id = o.id,
name = o.name,
suborders = (from so in gj select new Suborder
{
so.id,
so.name
}).ToList()
}).ToList();
解决方案最终非常简单。关键是使用组联接来获取 SQL 对子订单进行左联接,并添加第二个 ToList() 调用以强制运行查询,这样您就不会尝试在 SQL 服务器上创建对象。
orders = Context.orders
.GroupJoin(
Context.suborders,
o => o.id,
so => so.order_id,
(o, so) => new { order = o, suborders = so })
.ToList()
.Select(r => new Order
{
id = r.order.id,
name = r.order.name,
suborders = r.suborders.Select(so => new Suborder
{
id = so.id,
name = so.name
}.ToList()
}).ToList();
此代码仅对所有对象及其子对象进行一次 SQL 查询。它还允许您将 EF 对象转换为所需的任何对象。
我总是为关系创建一个虚拟化属性
因此,只需将(添加属性)扩展到您的订单类:
public class Order{
...
List<Suborder> _suborders;
public List<Suborder> Suborders{
get {
return _suborders ?? (_suborders = MyContext.Suborders.Where(X=>X.order_id==this.id).ToList());
}
...
}
因此,只有在您调用getters时,才会获取(提取)数据
这段代码怎么样?
您可以获取本地缓存。
List<Orders> orders = new List<Orders>();
private void UpdateCache(List<int> idList)
{
using (var db = new Test(Settings.Default.testConnectionString))
{
DataLoadOptions opt = new DataLoadOptions();
opt.LoadWith<Orders>(x => x.Suborders);
db.LoadOptions = opt;
orders = db.Orders.Where(x => idList.Contains(x.Id)).ToList();
}
}
private void DumpOrders()
{
foreach (var order in orders)
{
Console.WriteLine("*** order");
Console.WriteLine("id:{0},name:{1}", order.Id, order.Name);
if (order.Suborders.Any())
{
Console.WriteLine("****** sub order");
foreach (var suborder in order.Suborders)
{
Console.WriteLine("'torder id:{0},id{1},name:{2}", suborder.Order_id, suborder.Id, suborder.Name);
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
UpdateCache(new List<int> { 0, 1, 2 });
DumpOrders();
}
输出示例如下
*** order
id:0,name:A
****** sub order
order id:0,id0,name:Item001
order id:0,id1,name:Item002
order id:0,id2,name:Item003
*** order
id:1,name:B
****** sub order
order id:1,id0,name:Item003
*** order
id:2,name:C
****** sub order
order id:2,id0,name:Item004
order id:2,id1,name:Item005