将 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]
)
我对 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]
)