简体   繁体   中英

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

I have the following EF6 linq query:

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

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?

If so can it be solved with a stored procedure or function on the SQL side?

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. The table has a little less than 1 million entries. 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. 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)

EDIT 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. Here is a link to try and solve the problem on an old sqlserver version if upgrade is not possible

As soon as you are using a local function to evaluate a condition the whole dataset has to be retrieved from the DB first.

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. This way, the condition is evaluated on the server and only the appropriate data is transfered to the client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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