2

特定の場所から 50 マイル以内にあるアイテムのリストを返そうとしています。

私の表(簡略化)は次のとおりです。

  • ID
  • 経度
  • 緯度
  • 状態
  • アクティブ

最初のクエリがあります:

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(geom: __p_3,
distance: ___maxDistance_4))' を翻訳できませんでした。

変換可能な形式でクエリを書き直すか、AsEnumerable()、AsAsyncEnumerable()、ToList()、または ToListAsync() への呼び出しを挿入して明示的にクライアント評価に切り替えます。詳細については、 https://go.microsoft.com/fwlink/?linkid=2101038を参照してください。

Startup.cs:

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

1 に答える 1

2

この機能を機能させるには、それらの座標をPointSQLgeographyフィールドに として保存する必要があります。これは、新しいプロパティの計算列として既存のモデルに簡単に追加できます。

// 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 で直接行う必要があります。

于 2020-12-09T23:19:14.183 に答える