将 SQL 查询翻译成 Entity Framework Core 2.1

Translate SQL query into Entity Framework Core 2.1

我对 Entity Framework Core v2.1 有点陌生,我的问题如下。

在我的例子中,有一个名为 ServiceCarrier 的 table,如下所示:

ServiceId CarrierId
-------------------
1         1  
2         1  
4         1  
1         2  
2         2  
5         2   
1         20028  
2         20028  
5         20028  

通过使用此 SQL 查询,我能够获得所需的结果集:

SELECT serviceid  
FROM T  
GROUP BY serviceid  
WHERE carrierid IN (1, 20028)  
HAVING count(*) = (SELECT COUNT(DISTINCT carrierid)  
                   FROM T 
                   WHERE carrierid IN (1, 20028));  

结果:

 ServiceId 
 ---------
 1  
 2  

我想将其转换为 Entity Framework Core 2.1。

在此先感谢您的帮助。

我能够为上述问题提供解决方案。我的解决方案如下所示。如果有人找到比这个解决方案更好的解决方案,请分享。

_dbContext.ServiceCarriers
.Where(sc => carriers.Any(c => c.CarrierId == sc.CarrierId))
.GroupBy(scg => scg.Service)
.Where(sc1 => sc1.Count() == _dbContext.ServiceCarriers
                             .Where(scc => carriers.Any(c => 
                                          c.CarrierId == scc.CarrierId))
                             .Select(t => t.CarrierId)
                             .Distinct()
                             .Count()
).Select(sr => sr.Key)
 .ToList();

你自己的解决方案是可以的,但问题是条件像

.Where(sc => carriers.Any(c => c.CarrierId == sc.CarrierId))

其中 carriers 是内存中集合导致 client evaluation,因此虽然它会产生正确的结果,但性能不会很好。

更好的方法是准备一个 id 集合并使用 Contains 方法,这是在 EF 中实现 SQL IN 运算符的 LINQ 等价物的典型方法(Core ):

var carrierIds = carriers.Select(e => e.CarrierId);

var result = db.ServiceCarriers
    .Where(sc => carrierIds.Contains(sc.CarrierId))
    .GroupBy(sc => sc.ServiceId)
    .Where(scg => scg.Count() == db.ServiceCarriers
        .Where(sc => carrierIds.Contains(sc.CarrierId))
        .Select(sc => sc.CarrierId)
        .Distinct()
        .Count()
    )
    .Select(scg => scg.Key)
    .ToList();

生成的 SQL 查询与原始查询几乎相同:

SELECT [sc].[ServiceId] AS [Key]
FROM [ServiceCarriers] AS [sc]
WHERE [sc].[CarrierId] IN (1, 20028)
GROUP BY [sc].[ServiceId]
HAVING COUNT(*) = (
    SELECT COUNT(*)
    FROM (
        SELECT DISTINCT [sc0].[CarrierId]
        FROM [ServiceCarriers] AS [sc0]
        WHERE [sc0].[CarrierId] IN (1, 20028)
    ) AS [t]
)