我从搜索页面获得此MySQL语句,用户输入邮政编码,并在输入的邮政编码的15密耳内找到最近的stiocklist。
SELECT * , (
(
ACOS( SIN( "+SENTLNG +" * PI( ) /180 ) * SIN( s_lat * PI( ) /180 ) + COS( " + SENTLNG +" * PI( ) /180 ) * COS( s_lat * PI( ) /180 ) * COS( (
" + SENTLANG + " - s_lng
) * PI( ) /180 ) ) *180 / PI( )
) *60 * 1.1515
) AS distance_miles
FROM new_stockists
WHERE s_lat IS NOT NULL
HAVING distance_miles <15
ORDER BY distance_miles ASC
LIMIT 0 , 15
但现在我正在使用linq和亚音速,并没有弄清楚如何在linq或亚音速中做到这一点 你的帮助将不胜感激,也请注意,我不得不发送一个动态的地址,这就是页面顶部提到的邮政编码,我打电话给谷歌,然后获取lng和lat给他们的邮政编码给出
答案 0 :(得分:2)
您可以在MS SQL中创建一个存储过程来执行查询所执行的操作,然后从您的应用程序中调用该查询。 Linq确实支持存储过程 - 有点像这样
partial class StockistsDataContext
{
[Function(Name = "dbo.NewStockistsByDistance")]
public ISingleResult<NewStockist> NewStockistsByDistance(
[Parameter(DbType = "Int", Name = "s_lat")] int lat,
[Parameter(DbType = "Int", Name = "s_lng")] int lng)
{
var result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), lat, lng);
return ((ISingleResult<NewStockist>)(result.ReturnValue));
}
}
回退到存储过程有点恼火,但我不认为解析Queryables表达式的Linq部分可以检测到revant数学函数并将它们映射到SQL。
答案 1 :(得分:0)
我建议(如果可能)获取邮政编码的中心点,然后应用Haversine公式查找特定半径范围内的所有商店。
此处的公式以千米为单位。
您必须更改相关数字,它才能行驶数英里。
例如:将6371.392896转换为里程。
宣布@radiusInKm为FLOAT
DECLARE @ lat2Compare AS FLOAT
DECLARE @ long2Compare AS FLOAT
SET @radiusInKm = 5.000
SET @ lat2Compare = insert_your_lat_to_compare_here
SET @ long2Compare = insert_you_long_to_compare_here
SELECT * FROM insert_your_table_here WITH(NOLOCK) WHERE(6371.392896 * 2 * ATN2(SQRT((sin((弧度(GeoLatitude - @ lat2Compare))/ 2)* sin((弧度(GeoLatitude - @ lat2Compare))/ 2))+(cos(弧度(GeoLatitude)) * cos(弧度(@ lat2Compare))* sin(弧度(GeoLongitude - @ long2Compare)/ 2)* sin(弧度(GeoLongitude - @ long2Compare)/ 2))) ,SQRT(1 - ((sin((弧度(GeoLatitude - @ lat2Compare))/ 2)* sin((弧度(GeoLatitude - @ lat2Compare))/ 2))+(cos(弧度(GeoLatitude))* cos(弧度) (@ lat2Compare))* sin(弧度(GeoLongitude - @ long2Compare)/ 2)* sin(弧度(GeoLongitude - @ long2Compare)/ 2))) )))&lt; = @radiusInKm
如果您想在C#中执行Haversine公式,
double resultDistance = 0.0;
double avgRadiusOfEarth = 6371.392896; //地球的半径不同,我取平均值。
// Haversine公式
//距离= R * 2 * aTan2(A的平方根,1 - A的平方根)
//其中A =正方形平方(纬度差/ 2)+(纬度1的余弦值*纬度2 *正弦平方的余弦值(经度/ 2的差值))
//和R =地球的周长
double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare);
double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare);
double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude))* Math.Cos(DegreeToRadian(latitudeToCompare))* Math.Sin(differenceInLong / 2)* Math.Sin(differenceInLong / 2);
double aFormula =(Math.Sin((differenceInLat)/ 2)* Math.Sin((differenceInLat)/ 2))+(aInnerFormula);
resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula),Math.Sqrt(1 - aFormula));
DegreesToRadian是我自定义创建的函数 它是“Math.PI * angle / 180.0”的简单1衬里
对于LINQ,您可以使用C#数学函数以及所有C#检查。例如:!=等于不等等。
请参阅以下示例
它不完整,所以请根据自己的喜好进行调整。
var linqQuery = from linqCollection in insert_your_collection_here
其中s_lat!=什么都没有 选择Math.ACos(Math.Sin(DegreesToRadian(sentlng) * Math.Pi / 180))
查看下面的MSDN链接,了解所有简单的LINQ示例。玩弄它,希望这有帮助
答案 2 :(得分:-1)
使用SQL的这一部分在SQL Server中创建一个新视图:
SELECT * , (your equation here) as distance
FROM new_stocklists
WHERE s_lat is not NULL
然后,您可以为视图创建Linq对象(SQLMetal将执行此操作或在Visual Studio中执行Linq to SQL)。然后,您可以使用Linq查询此视图。假设您的对象是StockDistance:
var list = db.StockDistance.Where(x=>x.distance<15)
.OrderBy(x=>x.distance)
.Take(15);