问题
I am currently working on an application that will retrieve other users' locations based on distance.
I have a database that store all the user location information in latitude and longitude. Since the calculation of distance between these two pairs of latitude and longitude is quite complicated, I need a function to handle it.
from a in db.Location.Where(a => (calDistance(lat, longi, Double.Parse(a.latitude), Double.Parse(a.longitude)))<Math.Abs(distance) )) {...}
However, I got the following error: LINQ to Entities does not recognize the method and this method cannot be translated into a store expression.
I don't know how to translated it into a store expression and also, the calculation also need the math library.
Is there any method that i can do to let the LINQ expression call my own function?
Maybe there are other ways to achieve my goal, can anyone help?
回答1:
I don't really know LINQ, but assuming that you can only send simple constraints in the query, I would construct a method that basically does the inverse of calDistance - take a coordinate and a distance and convert it into a bounding box with a minimum longitude, maximum longitude, minimum latitude, and maximum latitude.
You should be able to construct a simple query that will serve your purposes with those constraints.
something like (using Java here):
public double[] getCoordinateBounds(double distance, double longitude, double latitude) {
double[] bounds = new double[4];
bounds[0] = longitude - distanceToLongitudePoints * (distance);
bounds[1] = longitude + distanceToLongitudePoints * (distance);
bounds[2] = latitude - distanceToLatitudePoints * (distance);
bounds[3] = latitude + distanceToLatitudePoints * (distance);
return bounds;
}
Then you could construct a query.
double[] bounds = getCoordinateBounds(distance, longi, lat);
var nearbyUserLocations = from a in db.Location
where longitude > bounds[0] and longitude < bounds[1]
and latitude > bounds[2] and latitude < bounds[3]
This would give you a box of points rather than a radius of points, but it would be few enough points that you could then process them and throw out the ones outside your radius. Or you might decide that a box is good enough for your purposes.
回答2:
LinqToEntities won't allow you to call a function, it doesn't even allow ToString()
this is not a Linq thing its a LinqToEntities restriction
you could put your code in to the database as a Stored Proc or Function and call it using ExecuteStoreQuery
see here Does Entity Framework Code First support stored procedures?
回答3:
The problem you see is that the LINQ to SQL engine is trying to inject T-SQL from your user-defined function and it cannot. One (albeit nasty) option is to retrieve all of your locations and then calculate from that result set.
var locations = db.Location.ToList();
locations = locations.Where(a => (calDistance(lat, longi, Double.Parse(a.latitude), Double.Parse(a.longitude))).ToList();
来源:https://stackoverflow.com/questions/9789124/how-to-call-user-defined-function-in-linq-in-my-visual-c-sharp-web-service-for-m