EF服务器上的分组问题

本文关键字:问题 服务器 EF | 更新日期: 2023-09-27 18:01:38

我在使用实体框架进行分组时遇到了这个问题。

。Net: 4.5, EF: 5.0,数据库:Oracle

我的问题是当我在服务器上分组并返回数据时,分组数据(实体列表)一遍又一遍地返回所有分组数据的第一个记录-但组KEY是正确的。

如果我不按预期的记录返回一个组,但我有一些分组要求,我的解决方案是…是的,这让我感觉不太好,代码应该可以工作…但它没有。

x。D = string rest is integer/string mix.

下面是不能工作的代码:

db.ENTITY_NAME
.Where(x =>
       wantedGs.Contains(x.G) &&
       wantedAs.Contains(x.A)
    )
.GroupBy(x => x.D)
.ToList()
.Select(x => x.FirstOrDefault())
.Select(x => new MyEntity
    {
        A = x.A,
        B = x.B,
        C = x.C,
        E = x.E,
        D = x.D,
        F = x.F,
        G = x.G
    })
.ToList();

这是我想要做的工作:

db.ENTITY_NAME
.Where(x =>
       wantedGs.Contains(x.G) &&
       wantedAs.Contains(x.A)
    )
.Select(x => new
{
    x.A,
    x.B,
    x.C,
    x.D,
    x.E,
    x.F,
    x.G
})
.ToList()
.GroupBy(x => x.D)
.Select(x => x.FirstOrDefault())
.Select(x => new MyEntity
    {
        A = x.A,
        B = x.B,
        C = x.C,
        E = x.E,
        D = x.D,
        F = x.F,
        G = x.G
    })
.ToList();

EF服务器上的分组问题

如果这不起作用,请发布一些显示问题的示例数据

db.ENTITY_NAME
.Where(x =>
       wantedGs.Contains(x.G) &&
       wantedAs.Contains(x.A)
    )
.GroupBy(x => x.D)
.Select(x => x.FirstOrDefault())
.AsEnumerable()
.Select(x => new MyEntity
    {
        A = x.A,
        B = x.B,
        C = x.C,
        E = x.E,
        D = x.D,
        F = x.F,
        G = x.G
    })
.ToList();

我发现LINQPad在诊断这类问题时很有用。对一个Oracle表进行查询,并从Results选项卡切换到SQL选项卡,注意第一个示例如何导致一个初始SQL select,随后是多个select语句,这些语句对于实现所需的适当分组是没有帮助的。我看像个bug。

这个问题似乎是oracle特有的(可能是特定的客户端版本)。类似的GroupBy在Microsoft SQL Express数据库上给出了正确的结果,尽管也有多个SQL select s。

在数据库连接上使用GroupBy时,我们似乎需要小心;它可以更快,更准确地评估早期(例如转换到一个列表),这样我们就可以使用LINQ从那个点开始的数据。

使用repro case更新:

首先是Oracle (9i)表创建和行插入:

create table payees (
   name varchar2(10),
   amount number(5));
insert into payees values ('JACK', 150);
insert into payees values ('BARRY', 100);
insert into payees values ('EMMA', 20);
insert into payees values ('FLAVIA', 15);
insert into payees values ('SYLVIA', 300);
commit;

好的和坏的LINQ语句(使用Oracle 9i客户端):

var good = Payees.ToList().GroupBy(p => p.Amount / 100);
var bad = Payees.GroupBy(p => p.Amount / 100);

一个我期望智能LINQ to Oracle驱动程序使用的查询示例:

select trunc(amount/100) pay_category, name, amount
from payees
order by pay_category;
PAY_CATEGORY NAME           AMOUNT
------------ ---------- ----------
           0 EMMA               20
           0 FLAVIA             15
           1 JACK              150
           1 BARRY             100
           3 SYLVIA            300

LINQPad在SQL选项卡中报告的实际奇怪查询,导致根本没有有用的分组:

SELECT t0.AMOUNT
FROM GENSYS.PAYEES t0
GROUP BY t0.AMOUNT
SELECT t0.AMOUNT, t0.NAME
FROM GENSYS.PAYEES t0
WHERE ((t0.AMOUNT IS NULL AND :n0 IS NULL) OR (t0.AMOUNT = :n0))
-- n0 = [15]
SELECT t0.AMOUNT, t0.NAME
FROM GENSYS.PAYEES t0
WHERE ((t0.AMOUNT IS NULL AND :n0 IS NULL) OR (t0.AMOUNT = :n0))
-- n0 = [20]
SELECT t0.AMOUNT, t0.NAME
FROM GENSYS.PAYEES t0
WHERE ((t0.AMOUNT IS NULL AND :n0 IS NULL) OR (t0.AMOUNT = :n0))
-- n0 = [100]
SELECT t0.AMOUNT, t0.NAME
FROM GENSYS.PAYEES t0
WHERE ((t0.AMOUNT IS NULL AND :n0 IS NULL) OR (t0.AMOUNT = :n0))
-- n0 = [150]
SELECT t0.AMOUNT, t0.NAME
FROM GENSYS.PAYEES t0
WHERE ((t0.AMOUNT IS NULL AND :n0 IS NULL) OR (t0.AMOUNT = :n0))
-- n0 = [300]

我可能对LINQ to SQL期望过高。(我的LINQPad报告LINQPad驱动程序是IQ V2.0.7.0,如果有帮助的话)。