Simple procedures in Linq To SQL
-
15-10-2019 - |
문제
My app is a client-server setup, where the client asks the servers for objects in a given region. It will send the server x and y coordinates, and a radius. The server then has to query an SQL Server database for objects in the specified region. In the database, the objects are stored by their x and y coordinates.
First I tried a contains
method in the Region
object passed to the server over WCF. Well, of course that didn't work because it couldn't convert the method to T-SQL. But I had seen simple lambda expressions being used in linq queries, so I tried this:
Func<UniverseStationaryObject, RegionLocation, bool> contains =
(universeObject, location) => Math.Sqrt(
Math.Pow(universeObject.locationX - location.x, 2) +
Math.Pow(universeObject.locationY - location.y, 2)
) <= location.radius;
var objects = from o in dataContext.UniverseStationaryObjects
where contains.Invoke(o, Location)
select o;
Unfortunately, this didn't work either -- I have read that some functions are allowed in Linq to SQL queries, but I guess math functions are not among them? Do I need a stored function for this? What would the stored function look like (I've never written one in T-SQL)? Can I pass C# objects to the functions and avoid extracting every value to pass to the db server? I mean, when I add the stored functions to the linq-to-sql classes designer, can I make it accept an object and extract the values at that point?
Note that it's not an option to retrieve every object and filter them in C#.
해결책
You'd need to make contains()
a compiled query using System.Data.Linq.CompiledQuery.Compile()
. It requires a slight modification to your query for it to work. I believe something like this would work:
Func<MyDataContext, UniverseStationaryObject, RegionLocation, bool> contains =
CompiledQuery.Compile(
(MyDataContext dc, UniverseStationaryObject universeObject, RegionLocation location) =>
Math.Sqrt(
Math.Pow(universeObject.locationX - location.x, 2) +
Math.Pow(universeObject.locationY - location.y, 2)
) <= location.radius);
var objects = from o in dataContext.UniverseStationaryObjects
where contains(dataContext, o, Location)
select o;
See also: Creating reusable chunks of LINQ to SQL