オリジナル住所: https://www.cnblogs.com/hucheng/p/9885573.html
SQLの実装
選択する es_name、 es_lon、 es_lat、 ROUND ( 6378.138 * 2 * ASIN ( SQRT ( 捕虜( SIN ( ( 30.611842 * PI()/ 180 - es_lat * PI()/ 180 )/ 2 )、 )+ COS(30.611842 * PI()/ 180)* COS(es_lat * PI()/ 180)* POW( SIN ( ( 104.074666 * PI()/ 180 - es_lon * PI()/ 180 )/ 2 )、 ) ) )* 1000年 )AS distance_um FROM c_ershuai ORDER BY distance_um ASC
ここで私はプログラムを使用したものです
まず、緯度および経度情報を有するエンティティを表すために使用されるインターフェイスを定義します。
/// <まとめ> /// 有する緯度及び経度 /// </要約> パブリック インターフェイスIHasLngAndLat { /// <要約> /// 经度 /// </要約> ダブル LNG { 取得します。セット; } /// <要約> /// 纬度 /// </要約> ダブル緯度{ 得ます。セット; } }
そして、一般的なクラスがパッケージの距離を計算するのに使用されて作成します。
/// <要約> /// 距離データ /// </要約> /// <typeParam名= "TEntity"> </ typeParam> パブリック クラス DataWithDistance <TEntity> { /// <要約> /// 距离(キロ) /// </要約> 公共 ダブルの距離{ 取得します。セット; } /// <要約> /// 实体数据 /// </要約> 公共 TEntityエンティティ{ 得ます。セット; } }
最後に、距離のランキングに基づいて拡張メソッドを書きます
注:この方法が使用され SqlFunctionsの クラスのみサポート のSQLServer データベースに必要他のデータベース、場合 SqlFunctionsは、 対応するクラスで置き換えます
/// <まとめ> /// のIQueryableは、によって拡張 /// </要約> パブリック 静的 クラスQueryableExtension { /// <要約> /// 根据距离排序 /// </要約> /// <typeparam名= "TEntity"> </ typeparam> /// <PARAM NAME = "照会可能"> </ param>の / // ます。<param name = "LNG"> 经度</ param>の /// <PARAM NAME = "LAT"> 纬度</ param>の /// <リターン> </リターン> パブリック 静的のIQueryable <DataWithDistance <TEntity >> OrderByDistance <TEntity>(本のIQueryable <TEntity>照会可能、ダブル LNG、重 LAT)どこ TEntity:クラス、IHasLngAndLat { VaRの RTN = から Q で照会可能 radLat1ましょう =緯度*にMath.PI / 180.0 ましょうradLat2 = q.Lat *にMath.PI / 180.0 ましょう - = radLat1 radLat2を Bせ = LNGは*にMath.PI / 180.0 q.Lng *にMath.PI / - 180.0 LET S = 2 * SqlFunctions.Asin(SqlFunctions.SquareRoot(Math.Pow((二重)SqlFunctions.Sin(/ 2)、2)+ SqlFunctions.Cos(radLat1) * SqlFunctions.Cos(radLat2)* Math.Pow((二重)SqlFunctions.Sin(B / 2)、2)))* 6378.137 LETさd =恐らくMath.round((二重)S * 10000)/ 10000 ORDERBYは、dが 選択します 新しい DataWithDistance <TEntity> {エンティティ= Q、距離= D}。 リターンRTN。 } }
これは、ソート機能の距離に応じて、エンティティフレームワークを完了します。
次に、我々は小さなデモを書くためにそれを使用します
最初の緯度および経度フィールドと、ストア・エンティティタイプを作成し、実現 IHasLngAndLat インタフェース
/// <要約> /// ストアエンティティ /// </要約> パブリック クラスショップ:IHasLngAndLat { /// <要約> /// 主键 /// </要約> 公共 のint Idを{ 取得 ; セット; } /// <要約> /// 商店名称 /// </要約> [必須] [StringLengthに(64 )] パブリック 文字列 ShopName { 得ます。セット; } /// <要約> /// 经度 /// </要約> 公共 ダブル LNG { 得ます。セット; } /// <要約> /// 纬度 /// </要約> 公共 ダブル緯度{ 得ます。セット; } }
そして、EFコンテキストクラスを作成します
/// <要約> /// EFコンテキスト /// </要約> パブリック クラスDemoDbContext:DbContext { 公共DemoDbContext() :ベース(" 名前= DemoDbContext " ) { } パブリック 仮想 DbSet <ショップ>ショップ{ 取得します。セット; } }
最後に、我々は、クエリストアをページングやソート近くから遠くまでの距離に応じて
二重 user_lng = 113.46、user_lat = 22.27 ; // ユーザー経度 INT pageIndexパラメータ= 3 ; // 現在のページ INTのpageSize = 10 ; // のページ番号 使用して(DemoDbContextコンテキスト= 新しいDemoDbContext()) { VAR照会= 。context.Shop.AsNoTracking()AsQueryable(); IQueryable <DataWithDistance <>> sort_queryable = queryable.OrderByDistanceショップ(user_lng、user_lat); // 付近からのユーザの距離に応じてはるかにソート 一覧<DataWithDistance <データ= sort_queryable.Skipショップ>>((pageIndexパラメータ- 1)*のpageSize) .Take(pageSizeを).ToList(); // ページとデータを取得するためのSQLクエリを実行 // TODO:DTOに見つかったデータオブジェクトをマッピングし、クライアントに返さ }
まあ、並べ替え、それがすべて完了距離で実装エンティティフレームワーク。