如何以一对多关系过滤子表上的列

时间:2017-04-13 08:21:44

标签: c# linq linq-to-sql entity-framework-core

我正在尝试编写一个过滤父表中字段的查询,包括子表,还过滤子表中的字段。

我通过在子选择器中放置ToList来实现这一点,但这对我来说感觉不对。这是正确的方法吗?

示例:

var query = _context.Set<order_header>()
                    .Where(oh => oh.customer == accountNo)
                    .Include(oh => oh.route_details)
                    .Select(oh => new order_header()
                    {
                        customer = oh.customer,
                        order_no = oh.order_no,
                        //other columns omitted
                        route_details = oh.route_details
                                          .Select(rd => new route_detail() { route_code = rd.route_code})
                                          .ToList()//this is odd
                    });
        return query.ToList();

修改: 我已经启用了SQL跟踪,我可以看到这是一个单独的查询来获取每个父行的子代。所以这绝对是做事的错误方式。

我开始认为我必须将结果选择为匿名类型,然后生成EF模型。

EDIT2 : 我现在已经删除了子查询选择中的ToList,但SQL跟踪显示这仍然是为每个父行运行查询。

代码:

var query = _context.Set<order_header>()
                    .Where(oh => oh.customer == accountNo)
                    .Include(oh => oh.route_details)
                    .Select(oh => new
                    {
                        customer = oh.customer,
                        order_no = oh.order_no,
                        //other columns omitted
                        route_details = oh.route_details.Select(rd =>  rd.route_code)
                    });
var result = query.ToList();
var list = new List<order_header>();
list.AddRange(result.Select(a =>
new order_header()
{
    customer = a.customer,
    order_no = a.order_no,
    //other columns omitted
    route_details = a.route_details.Select(rc => new route_detail() { route_code = rc }).ToList()
}));
return list;

EDIT3 根据要求,SQL跟踪:

父查询

exec sp_executesql N'SELECT [oph].[customer], [oph].[order_no], [oph].[customer_order_no], [oph].[date_received], [oph].[date_required], [oph].[date_despatched], [oph].[status], [oph].[to_reference], [oph].[from_reference], [oph].[nett_value]
FROM [scheme].[order_header] AS [oph]
WHERE [oph].[customer] = @__accountNo_0',N'@__accountNo_0 varchar(8)',@__accountNo_0='ACC_NO'

儿童查询

exec sp_executesql N'SELECT [avl].[route_code]
FROM [scheme].[route_detail] AS [avl]
WHERE @_outer_order_no = [avl].[ldordno]',N'@_outer_order_no varchar(10)',@_outer_order_no='1A469499  '

imgur链接 http://i.imgur.com/Q4ATQiU.png

请注意,图片中的架构名称不同,因为我一直在为问题编辑它们。

1 个答案:

答案 0 :(得分:0)

您可以使用匿名类型进行选择,然后应该生成一个具有适当联接的查询,类似这样(不确定我的导航属性是否正确):

var query = from oh in _context.Set<order_header>()
            where oh.customer == accountNo
            select new
            {
                oh,
                oh.route_details,
                oh.customer,
                // other navigation properties to include
                route_details = from rd in oh.route_details
                                // your child table filtering here
                                select new
                                {
                                    rd,
                                    rd.route_code,
                                    // other child nav properties to include
                                }
            };

return query.AsEnumerable().Select(m => m.oh).ToList();