рассчитать расстояние с помощью linq или дозвуковой - PullRequest
2 голосов
/ 04 марта 2010

У меня есть этот оператор MySQL со страницы поиска, пользователь вводит туда почтовый индекс и находит ближайший список воспроизведения в течение 15 миль от введенного почтового индекса.

 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 и subsonic и не понимаю, как это сделать в linq или subsonic Ваша помощь будет высоко ценится, пожалуйста, также не то, что мне нужно отправлять в динамическом от адреса, это почтовый индекс, указанный в верхней части страницы, я звоню в Google, чтобы получить затем lng и lat от них для данного почтового индекса .

Ответы [ 3 ]

2 голосов
/ 05 марта 2010

Вы можете создать хранимую процедуру в 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));
    }
}

Немного раздражает возвращаться к хранимым процессам, но я не думаю, что та часть Linq, которая анализирует деревья выражений Queryables, может обнаружить математические функции и сопоставить их с SQL.

0 голосов
/ 10 июня 2010

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

Формула здесь указана в километрах.
Вам нужно изменить соответствующие цифры, и она будет работать за мили.
Например: конвертировать 6371,392896 в мили.

ОБЪЯВИТЬ @radiusInKm AS FLOAT
ОБЪЯВИТЬ @ lat2Сравнить как плавать
ОБЪЯВИТЬ @ long2Сравнить как плавать
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))) ))) <= @ radiusInKm </p>

если вы хотите выполнить формулу Haversine в C #,

double resultDistance = 0.0;
double avgRadiusOfEarth = 6371,392896; // Радиусы Земли отличаются, я беру среднее.

// Формула Haversine
// расстояние = R * 2 * aTan2 (квадратный корень из A, квадратный корень из 1 - A)
// где A = синус в квадрате (разница в широте / 2) + (косинус широты 1 * косинус в широте 2 * синус в квадрате (разница в долготе / 2))
// и R = окружность земли

double разностьInLat = DegreeToRadian (currentLatitude - latitudeToCompare);
double разностьInLong = DegreeToRadian (currentLongitude - longtitudeToCompare);
удваивается double aFormula = (Math.Sin ((diffInLat) / 2) * Math.Sin ((diffInLat) / 2)) + (aInnerFormula);
resultDistance = avgRadiusOfEarth * 2 * Math.Atan2 (Math.Sqrt (aFormula), Math.Sqrt (1 - aFormula));

DegreesToRadian - это функция, которую я создал.
Это простой 1 вкладыш "Math.PI * angle / 180.0"

Для LINQ вы можете использовать математические функции C #, а также все проверки C #. Например:! = Равно не равно и т. Д.
В качестве примера смотрите следующее.
Он не полный, поэтому, пожалуйста, настройте его по своему вкусу.

var linqQuery = из linqCollection в insert_your_collection_here
где s_lat! = ничего
выберите Math.ACos (Math.Sin (DegreesToRadian (sentlng)) * Math.Pi / 180))

Посмотрите ссылку MSDN ниже для всех простых примеров LINQ. Поиграйте с этим, надеюсь, это поможет

Моя запись в блоге - SQL Haversine

MSDN - 101 образец LINQ

0 голосов
/ 04 марта 2010

Создайте новое представление в SQL Server, используя эту часть SQL:

SELECT * , (your equation here) as distance
FROM new_stocklists
WHERE s_lat is not NULL

Затем вы можете создать объект Linq для вашего представления (SQLMetal сделает это или Linq to SQL в Visual Studio). Затем вы можете использовать Linq для запроса этого представления. Допустим, ваш объект StockDistance:

var list = db.StockDistance.Where(x=>x.distance<15)
    .OrderBy(x=>x.distance)
    .Take(15);
...