简体   繁体   中英

How to call user defined function in LINQ in my visual C# web service for my android application?

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?

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?

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();

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.

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