Как вызвать пользовательскую функцию в LINQ в моем веб-сервисе Visual C# для моего приложения для Android?
В настоящее время я работаю над приложением, которое будет извлекать местоположения других пользователей на основе расстояния.
У меня есть база данных, в которой хранится вся информация о местоположении пользователя по широте и долготе. Поскольку вычисление расстояния между этими двумя парами широты и долготы довольно сложно, мне нужна функция для его обработки.
from a in db.Location.Where(a => (calDistance(lat, longi, Double.Parse(a.latitude), Double.Parse(a.longitude)))<Math.Abs(distance) )) {...}
Однако я получил следующую ошибку: LINQ to Entities не распознает метод, и этот метод не может быть преобразован в выражение хранилища.
Я не знаю, как перевести его в выражение магазина, а также, для расчета также нужна математическая библиотека.
Есть ли какой-нибудь метод, который я могу сделать, чтобы выражение LINQ вызывало мою собственную функцию?
Может быть, есть другие способы достижения моей цели, кто-нибудь может помочь?
3 ответа
Я действительно не знаю LINQ, но предполагая, что вы можете отправлять только простые ограничения в запросе, я бы сконструировал метод, который в основном делает обратное calDistance - взять координату и расстояние и преобразовать его в ограничивающий прямоугольник с минимумом долгота, максимальная долгота, минимальная широта и максимальная широта.
Вы должны быть в состоянии создать простой запрос, который будет служить вашим целям с этими ограничениями.
что-то вроде (используя Java здесь):
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;
}
Тогда вы могли бы построить запрос.
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]
Это даст вам коробку точек, а не радиус точек, но будет достаточно нескольких точек, чтобы вы могли затем обработать их и выбросить те, которые находятся за пределами вашего радиуса. Или вы можете решить, что коробка достаточно хороша для ваших целей.
LinqToEntities не позволит вам вызывать функцию, она даже не позволяет ToString()
это не вещь Linq, это ограничение LinqToEntities
Вы можете поместить свой код в базу данных в качестве сохраненного процесса или функции и вызвать его с помощью ExecuteStoreQuery
см. здесь. Поддерживает ли Entity Framework Code First хранимые процедуры?
Проблема, которую вы видите, состоит в том, что движок LINQ to SQL пытается внедрить T-SQL из вашей пользовательской функции и не может этого сделать. Один (хотя и неприятный) вариант - получить все ваши местоположения, а затем рассчитать на основе этого набора результатов.
var locations = db.Location.ToList();
locations = locations.Where(a => (calDistance(lat, longi, Double.Parse(a.latitude), Double.Parse(a.longitude))).ToList();