【问题标题】:Linq query with several left join generate few query具有多个左连接的 Linq 查询生成很少的查询
【发布时间】:2018-11-10 01:28:51
【问题描述】:

我尝试使用 Entity Framework Core 在 asp core 2 上通过 linq 编写查询,一切正常,查询返回正确的结果,但速度很慢。

var Query1 =
        from demand in _prabacontext.Demand
        join demandspec in _prabacontext.DemandSpec on demand.Id equals demandspec.DemandId into demandspecGroup
        join manager in _prabacontext.Manager on demand.ManagerId equals manager.Id into managerGroup
        from m in managerGroup.DefaultIfEmpty()
        join contractor in _prabacontext.Contractor on demand.ContractorId equals contractor.Id into contractorGroup
        from c in contractorGroup.DefaultIfEmpty()
        join company in _prabacontext.Company on c.CompanyId equals company.Id into companyGroup
        from cm in companyGroup.DefaultIfEmpty()
    where demand.RegDate >= Convert.ToDateTime("2018-01-01T00:00:00")
        select new
        {
            demand.Id,
            demand.Id1,
            RegDate = demand.RegDate.ToString("yyyy-MM-dd"),
            demand.IsLgot,
            demand.ContractorId,
            demand.DocNumber,
            demand.DocStatus,
            demand.ManagerId,
            demand.Remark,
            StrSum = demandspecGroup.Sum(x => (decimal?)(x.Price * x.Quantity)) ?? 0,
            ContractorName = cm.Name,
            ManagerName = m.Name1//+' '+m.Name2+' '+m.Name3
        };

在调试器日志中,这个 linq 查询转换成这个 SQL 语句:

SELECT 
    "demand"."_ID" AS "Id0", 
    "demand"."Contractor_ID" AS "ContractorId", 
    "demand"."DocNumber", 
    "demand"."DocStatus", 
    "demand"."ID" AS "Id1", 
    "demand"."Insert_Date", 
    "demand"."Insert_User", 
    "demand"."IsLgot", 
    "demand"."IsTender", 
    "demand"."last_updated", 
    "demand"."Manager_ID" AS "ManagerId", 
    "demand"."RegDate", 
    "demand"."Remark" AS "Remark0", 
    "demandspec"."_ID", 
    "demandspec"."Commerc_ID", 
    "demandspec"."DeliveryDate", 
    "demandspec"."_Demand_ID", 
    "demandspec"."Demand_ID", 
    "demandspec"."FinType_ID", 
    "demandspec"."Goods2_ID", 
    "demandspec"."Goods_ID", 
    "demandspec"."GoodsUnion_ID", 
    "demandspec"."ID", 
    "demandspec"."last_updated", 
    "demandspec"."Price", 
    "demandspec"."Quantity", 
    "demandspec"."Remainder", 
    "demandspec"."Remark", 
    "demandspec"."Reserv"
FROM
    "Demand" AS "demand"
LEFT JOIN 
    "Demand_Spec" AS "demandspec" ON "demand"."_ID" = "demandspec"."_Demand_ID"
ORDER BY 
    "Id0"

SELECT "manager"."id", "manager"."name1"
FROM "manager" AS "manager"

SELECT "contractor"."id", "contractor"."company_id"
FROM "maxim"."contractor" AS "contractor"

SELECT "company"."id", "company"."name"
FROM "maxim"."company" AS "company"`

它从查询中返回数据并以编程方式连接输出数据。但是这张桌子很大。我知道我可以直接编写 SQL 查询,但我想使用 linq。

如何编写一个 Linq 查询,将其转化为带有几个左连接的 SQL 查询?

添加:

在调试日志中我发现了这样的字符串:

无法翻译 LINQ 表达式“DefaultIfEmpty()”并将在本地计算

对于查询中的每个表。如果没有这种结构,我如何重写我的查询?

【问题讨论】:

  • 从 SQL 查询形状看起来您使用的是 EF Core,这与 EF6 非常不同。请使用 entity-framework-core 标记并在问题中包含使用的确切版本,因为 SQL 查询翻译在 EF Core 版本之间有所不同(它仍在积极开发中)。
  • 感谢您的评论。我修好了。

标签: c# asp.net linq left-join entity-framework-core


【解决方案1】:

其中 demand.RegDate >= Convert.ToDateTime("2018-01-01T00:00:00")

这似乎在 TSQL 输出中丢失,因此必须在本地进行评估。如果这是在本地评估的,那么整个需求表正在加载,这就是查询运行缓慢的原因。

此外,如果您设置了导航属性,则无需编写这些连接。

这是我将如何编写相同的查询:

DateTime regDate = Convert.ToDateTime("2018-01-01T00:00:00");

var query1 =
    from demand in _prabacontext.Demand
    where regDate <= demand.RegDate
    let demandSpecs = demand.DemandSpecs
    let manager = demand.Manager
    let company = demand.Contractor.Company
    select new
    {
        demand.Id,
        demand.Id1,
        RegDate = demand.RegDate.ToString("yyyy-MM-dd"),
        demand.IsLgot,
        demand.ContractorId,
        demand.DocNumber,
        demand.DocStatus,
        demand.ManagerId,
        demand.Remark,
        StrSum = demandSpecs.Sum(x => (decimal?)(x.Price * x.Quantity)) ?? 0,
        ContractorName = company.Name,
        ManagerName = manager.Name1//+' '+manager.Name2+' '+manager.Name3
    };

【讨论】:

  • 感谢您的提示。我在 DemandSpec 上将“join”替换为“let”,这解决了问题。这会生成带有子查询的查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多