在DB中,我有两个具有一对多关系的表:
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-to-Entities获得相同的结果对象结构?请注意,我想从查询中获取新对象,而不是实体框架生成的对象。
以下内容让我接近,但抛出异常:“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();
答案 0 :(得分:1)
解决方案最终非常简单。关键是使用组连接来获取SQL以执行左连接到子命令,并添加第二个ToList()调用以强制运行查询,这样您就不会尝试在SQL服务器上创建对象。 / p>
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对象转换为您需要的任何内容。
答案 1 :(得分:0)
我总是创建一个虚拟化的关系属性
所以只需将(添加属性)扩展到您的订单类:
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
时才会获取(拉取)数据答案 2 :(得分:0)
这段代码怎么样?
您可以获得本地缓存。
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