【问题标题】:How to filter columns on child table in a one to many relationship如何以一对多关系过滤子表上的列
【发布时间】:2023-03-05 17:11:02
【问题描述】:

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

我通过将 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 模型。

编辑2: 我现在已经删除了子查询选择中的 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;

编辑3 根据要求,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  '

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

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

【问题讨论】:

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


    【解决方案1】:

    您可以使用匿名类型进行选择,然后会产生一个带有适当连接的查询,如下所示(不确定我的导航属性是否正确):

    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();
    

    【讨论】:

    • 这可行,但它仍在为每一行执行查询以获取子记录。你看到edit2了吗?
    • 您确定没有触发您的查询的延迟加载吗?我刚刚介绍了一个与我发布的示例类似的示例,并且只获得了 1 个带有所选导航属性连接的查询。
    • EF Core 尚不支持延迟加载,我忘了 :) 你能发布你的分析器输出吗?
    • 好的,您在我的查询中得到了相同的跟踪信息?
    • 您好,很抱歉耽搁了。今天才刚回来上班。这是您的代码的跟踪:标题跟踪pastebin.com/rS1Zz4Hv 详细跟踪:pastebin.com/NrvFweCm
    猜你喜欢
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 2018-04-26
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多