IsWithinDistance не удалось перевести

Я пытаюсь вернуть список предметов, которые находятся, скажем, в 50 милях от заданного местоположения.

Моя таблица (упрощенная) выглядит следующим образом:

  • Идентификатор
  • Долгота
  • Широта
  • Положение дел
  • Активный

У меня есть первоначальный запрос:

var query = db.MyTable.Where(o=> o.Status == "New" && o.Active == true);

query = query.Where(o => new Point(o.Longitude, o.Latitude)
                  .IsWithinDistance(new Point(_currentLongitude, _currentLatitude), 50));

var result = query.ToList()

Однако - похоже, это не работает, и я получаю сообщение об ошибке, как показано ниже - есть идеи, как это решить? или если есть лучший способ получить ближайшие предметы?

.Where(p => new Point(p.Longitude, p.Latitude) .IsWithinDistance(геометрия: __p_3,
Distance: ___maxDistance_4))' не удалось перевести.

Либо перепишите запрос в форме, которую можно перевести, либо явно переключитесь на оценку клиента, вставив вызов AsEnumerable(), AsAsyncEnumerable(), ToList() или ToListAsync(). См. https://go.microsoft.com/fwlink/?linkid=2101038 для получения дополнительной информации.

Запуск.cs:

services.AddDbContext<AppDbContext>(options =>
{
                
 options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
   x => x.UseNetTopologySuite());
});

Вам нужно сделать именно так, как предлагает сообщение об ошибке: «Либо перепишите запрос в форме, которую можно перевести, либо явно переключитесь на оценку клиента, вставив вызов либо AsEnumerable(), AsAsyncEnumerable(), ToList() или ToListAsync. (). Дополнительную информацию см. на странице go.microsoft.com/fwlink/?linkid=2101038.

Robert Harvey 09.12.2020 22:21

@RobertHarvey - это встроенная функция в Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite. См. Пространственные данные EF Core и Пространственные данные в поставщике SQL Server EF Core

Matt Johnson-Pint 09.12.2020 22:22

@Steve - Вы добавили .UseNetTopologySuite , как показано здесь ? (Кроме того, я предполагаю, что SQL Server, пожалуйста, подтвердите или исправьте.)

Matt Johnson-Pint 09.12.2020 22:23

@MattJohnson-Пинт: пока

Robert Harvey 09.12.2020 22:24

Насколько я могу судить, создание нового Point из широты/долготы на данный момент не поддерживается. Возможно, вам придется хранить ваши данные как тип Point в вашей модели.

ESG 09.12.2020 22:25

@RobertHarvey привет - да пробовал var xx = query = (IQueryable<Profile>)query.Where(o => new Point(o.Longitude, o.Latitude) .IsWithinDistance(new Point(_profile.Longitude, _profile.Latitude), _maxDistance)).ToList(); но все та же ошибка

Steve 09.12.2020 22:35

@MattJohnson-Pint Да - MS SQL 2019 Express, и да, уже добавлено в startup.cs (отредактировал ответ, чтобы показать, что я включил)

Steve 09.12.2020 22:37

не могли бы вы протестировать первую часть того, где конвертировать в список, а затем запустить второй фильтр db.MyTable.Where(o=> o.Status == "New" && o.Active == true).ToList();.

coder_b 09.12.2020 23:30

@coder_b - это нанесет ущерб цели пространственных запросов/индексов на стороне SQL и может привести к ненужному перемещению большого количества данных клиенту. Конечно, все зависит от того, сколько данных мы имеем в виду, но я бы не рекомендовал такой подход.

Matt Johnson-Pint 10.12.2020 18:28

Я полностью согласен, я проверял, что IsWithinDistance работает должным образом с отключенным набором данных. интересно, исключают ли какие-либо проблемы, связанные с конфигурациями и т. д.

coder_b 10.12.2020 19:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
10
884
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы эта функция работала, вам необходимо сохранить эти координаты как Point в поле SQL geography. Вы можете легко добавить это в существующую модель в качестве вычисляемого столбца для нового свойства.

// on your entity
public Point Coordinates { get; }

// in your db context's OnModelCreating
  modelBuilder.Entity<YourEntity>()
    .Property(x => x.Coordinates)
    .IsRequired()
    .HasComputedColumnSql("geography::Point(Latitude, Longitude, 4326)");

Обратите внимание, что SRID 4326 — это широко используемая система координат широта/долгота, поддерживаемая SQL Server. Подробнее об этом здесь.

Создайте свою модель и разверните ее в своей базе данных.

Теперь, когда у вас есть пространственное поле и свойство, вы можете сделать запрос следующим образом:

var point = new Point(_currentLongitude, _currentLatitude) { SRID = 4326 };
var distanceInMeters = 50 * 1609.344;  // 50 miles to meters conversion
var results = db.YourEntity
                .Where(x => x.Coordinates.IsWithinDistance(point, distanceInMeters))
                .ToList();

SRID 4326 использует метры для расстояния, поэтому обязательно конвертируйте, как показано выше, если вы используете мили.

Кроме того, если у вас много данных, вы также захотите добавить пространственный индекс в этот столбец, но EF Core пока не поддерживает это напрямую, поэтому вам придется делать это непосредственно в SQL.

Обратите внимание, что подход с вычисляемым столбцом является необязательным. Вы всегда можете иметь отдельное свойство Point, но тогда у вас не будет отдельных свойств широты и долготы.

Matt Johnson-Pint 10.12.2020 00:45

Привет, спасибо за быстрый ответ, я попробую это. Есть ли какая-либо польза от наличия/отсутствия вычисляемого столбца для точки?

Steve 10.12.2020 15:40

Поле Point (sql geography) — это необходимые данные для работы пространственных запросов. Вы можете просто заполнить Point и не включать отдельные поля широты и долготы. Наличие обоих в основном просто удобство.

Matt Johnson-Pint 10.12.2020 18:27

@MattJohnson-Pint, не могли бы вы взглянуть на это stackoverflow.com/questions/70847958/…

Fadi 25.01.2022 12:37

Другие вопросы по теме