问题描述
|
关于使用EF生成的此sql语句,是否有任何性能问题需要了解
C#代码:
public IQueryable<Lugar> NearestPOI(double lat,double lng,int> distance)
{
System.Data.Objects.ObjectResult<Int32?> AllowedPois = dbContext.SP_NearestPOI(lat,lng,100000);
IQueryable<Lugar> POI = from c in dbContext.Lugars
where AllowedPois.Contains(c.id)
select c;
return POI;
}
EF4生成的查询:
SELECT
[Extent1].[id] AS [id],[Extent1].[empresaId] AS [empresaId],[Extent1].[usuarioId] AS [usuarioId],[Extent1].[name] AS [name],[Extent1].[description] AS [description],[Extent1].[lat] AS [lat],[Extent1].[lng] AS [lng],[Extent1].[logoThumbnail] AS [logoThumbnail],[Extent1].[imageType] AS [imageType]
FROM [dbo].[Lugares] AS [Extent1]
WHERE [Extent1].[id] IN (1,2,3,4,5,6,7)
我担心的是,将AllowedPois查询作为一种单独的方法进行,它是对纯sql语法使用常规方法,就像这样:
SELECT * from dbo.Lugares L join dbo.NearestPOI(9.105306627167566,-79.38148587942118,100000) NL
on L.id = NL.id
由于我在该项目中使用EF4,因此我坚持使用它,并且不对查询使用字符串连接。我尝试使用这种方法来生成更引人注目的查询:
var POI = from c in dbContext.Lugars
join i in dbContext.SP_NearestPOI(lat,100000) on c.id equals i.Value
select c;
但是它给出了一个非常混乱的查询,该查询具有N个并集,该并集的数量随着allowedPois的数量而增加:
SELECT
[Extent1].[id] AS [id],[Extent1].[imageType] AS [imageType]
FROM [dbo].[Lugares] AS [Extent1]
INNER JOIN (SELECT
[UnionAll5].[C1] AS [C1]
FROM (SELECT
[UnionAll4].[C1] AS [C1]
FROM (SELECT
[UnionAll3].[C1] AS [C1]
FROM (SELECT
[UnionAll2].[C1] AS [C1]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
UNION ALL
SELECT
4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
UNION ALL
SELECT
5 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll4]
UNION ALL
SELECT
6 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable6]) AS [UnionAll5]
UNION ALL
SELECT
7 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable7]) AS [UnionAll6] ON [Extent1].[id] = [UnionAll6].[C1]
关于如何改进此操作的任何想法,还是应该使用单独的allowedPois查询坚持我的实际解决方案?
解决方法
您确实不应该在LINQ查询中使用连接语法。我的一部分希望他们不将LINQ的C#语言包含在join运算符中,因为这只会导致混乱,并且倾向于生成这样的错误SQL。原因是当您要执行where子句或在结果中包含该表时,几乎总是将SQL加入其中。 LINQ已经对此提供了强大的支持,但是您只需要以LINQ方式而不是SQL方式进行思考即可。您的LINQ数据模型应具有定义的关系,因此您不需要通过联接重新定义它们。由于您先使用了sproc,因此此处并不完全适用,但适用相同的原理。实际上,使用C#进行的第一个LINQ查询是有效的方法。
所以,如果我不清楚。这是正确的代码。
public IQueryable<Lugar> NearestPOI(double lat,double lng,int> distance)
{
System.Data.Objects.ObjectResult<Int32?> AllowedPois = dbContext.SP_NearestPOI(lat,lng,100000);
IQueryable<Lugar> POI = from c in dbContext.Lugars
where AllowedPois.Contains(c.id)
select c;
return POI;
}