문제

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top