简体   繁体   English

Entity Framework 是在数据库中还是在本地执行 C# 函数?

[英]Does Entity Framework execute C# functions in database or locally?

I have the following EF6 linq query:我有以下 EF6 linq 查询:

List<Segments> CloseSel = _context?.Segments
   .Where(sv => listGeos.Any(geo => sv.Geometry_Data.Distance(geo) <= radius))
   .ToList();

Basically gets geometry shapes (similar to osm) close to a geometry point, it works well and quite fast (less than 2 seconds) with a local database, but when I push for a remote database, the query takes so long it throws a timeout exception (it works for other queries that just gets objects by id so i know its not a connection issue).基本上得到接近几何点的几何形状(类似于 osm),它在本地数据库中运行良好且非常快(不到 2 秒),但是当我推送远程数据库时,查询需要很长时间,它会引发超时异常(它适用于仅通过 id 获取对象的其他查询,所以我知道它不是连接问题)。

Could it be possible that it executes the Distance() function locally and comes back to the C# side every time it tries to determine if the rows are close to the point?它是否有可能在每次尝试确定行是否接近点时在本地执行Distance() function 并返回 C# 端?

If so can it be solved with a stored procedure or function on the SQL side?如果是这样,是否可以通过存储过程或 SQL 端的 function 来解决?

EDIT: Here are a few more details, the local database is a mdf file, and the 'distant' one is the same mdf file attached to an sql server instance, which is the connection string i am using.编辑:这里有更多细节,本地数据库是一个 mdf 文件,而“远程”文件是附加到 sql 服务器实例的同一个 mdf 文件,这是我正在使用的连接字符串。 The table has a little less than 1 million entries.该表的条目少于 100 万个。 The Distance function is actually from the class System.Data.Entity.Spatial, which gets translated to STDistance in sql, so it should not be the reason it pulls the entire table.距离 function 实际上来自 class System.Data.Entity.Spatial,它在 sql 中被转换为 STDistance,所以它不应该是它拉整个表的原因。 Here is the translated query:这是翻译后的查询:

SELECT 
[Extent1].[Id_Segment] AS [Id_Segment], 
...
[Extent1].[Geometry_Data] AS [Geometry_Data]
FROM [dbo].[Segments] AS [Extent1]
WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM  (SELECT 
        geometry::STGeomFromText(N'POINT (35 30)', 0) AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
    UNION ALL
        SELECT 
        geometry::STGeomFromText(N'POINT (45 20)', 0) AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]
    ...
    UNION ALL
        SELECT 
        geometry::STGeomFromText(N'POINT (25 10)', 0) AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable13]) AS [UnionAll12]
    WHERE ([Extent1].[Geometry_Data].STDistance([UnionAll12].[C1])) <= 5
)

Now what's really curious is that it will take the query maybe 5 seconds in local, but if I try to execute it directly on the distant sql server it will take more than ten minutes (and i had to stop before the end)现在真正好奇的是,在本地查询可能需要 5 秒,但如果我尝试直接在远程 sql 服务器上执行它,则需要十多分钟(我不得不在结束前停止)

EDIT 2:编辑2:

Ok so turns out the distant database is using a 2012 sqlserver, which at the time was really not optimised for spatial data, since the wide spread of spatial data came a little later, when i tried it on a 2019 sqlserver it came whith the same performance as the mdf file since EF6 is implicitely handling the file as a newer version of sqlserver.好吧,事实证明,远程数据库使用的是 2012 sqlserver,当时它实际上并没有针对空间数据进行优化,因为空间数据的广泛传播来得稍晚一点,当我在 2019 sqlserver 上尝试它时,它也一样性能作为 mdf 文件,因为 EF6 隐含地将文件作为更新版本的 sqlserver 处理。 Here is a link to try and solve the problem on an old sqlserver version if upgrade is not possible如果无法升级,这是尝试解决旧 sqlserver 版本问题的链接

As soon as you are using a local function to evaluate a condition the whole dataset has to be retrieved from the DB first.一旦您使用本地 function 来评估条件,就必须首先从数据库中检索整个数据集。

To overcome that problem, create a UDF and either use its result in a calculated column or map it so it can be used inside LINQ queries.为了克服这个问题,创建一个 UDF 并将其结果用于计算列或map以便它可以在 LINQ 查询中使用。 This way, the condition is evaluated on the server and only the appropriate data is transfered to the client.这样,在服务器上评估条件,并且仅将适当的数据传输到客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM