将SQL查询转换为Entity Framework Core 2.1

时间:2018-07-08 16:53:59

标签: c# sql entity-framework-core .net-core-2.1

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

在我的情况下,有一个名为ServiceCarrier的表,如下所示:

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。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分: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();`

预先感谢

答案 1 :(得分:1)

您自己的解决方案还可以,但是问题是这样的情况

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

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

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

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]
)