3

这是我写的 Linq to Entities 声明。

public static List<Model.User> GetNearestUsers(int userid,int count,ref Model.HangoutDBEntities context)
    {
        Model.Location myLocation=GetCurrentLocation(userid,ref context);

        return context.Locations.Where(o => EntityFunctions.DiffMinutes(DateTime.Now, o.DateTimeStamp) <= 30).OrderBy(o => Core.Location.Distance.CalculateDistance(myLocation.Latitude, myLocation.Longitude, o.Latitude, o.Longitude)).Select(o => o.User).ToList();
    }

这是CalculateDistance方法

public static double CalculateDistance(decimal lat1,decimal lon1,decimal lat2,decimal lon2)
    {
        try
        {
            var R = 6371; // Radius of the earth in km
            var dLat = DegreeToRadian((double)(lat2 - lat1));  // Javascript functions in radians
            var dLon = DegreeToRadian((double)(lon2 - lon1));
            var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                    Math.Cos(DegreeToRadian((double)lat1)) * Math.Cos(DegreeToRadian((double)lat2)) *
                    Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            var d = R * c; // Distance in km

            return (double)d;
        }
        catch
        {
            return 0.0;
        }
    }

    public static double DegreeToRadian(double angle)
    {
        return Math.PI * angle / 180.0;
    }

请让我知道是否有任何解决方法。我得到一个例外

LINQ to Entities 无法识别方法 'Double CalculateDistance(System.Decimal, System.Decimal, System.Decimal, System.Decimal)' 方法,并且此方法无法转换为存储表达式。

我知道自定义函数不适用于 Linq 2 实体,但我不知道解决方法。你能帮帮我吗?:)

4

3 回答 3

3

将数据加载到列表中,然后对列表执行计算

    var origList = context.Locations.Where(o => EntityFunctions.DiffMinutes(DateTime.Now, o.DateTimeStamp) <= 30).ToList()

 var orderedList = origList.OrderBy(o => Core.Location.Distance.CalculateDistance(myLocation.Latitude, myLocation.Longitude, o.Latitude, o.Longitude)).Select(o => o.User).ToList();

或者;

context.Locations
    .Where(o => EntityFunctions.DiffMinutes(DateTime.Now, o.DateTimeStamp) <= 30).ToList()
        .OrderBy(o => Core.Location.Distance.CalculateDistance(myLocation.Latitude, myLocation.Longitude, o.Latitude, o.Longitude))
            .Select(o => o.User).ToList();

需要注意的是 where 子句之后的 ToList。

调用 ToList() 后,数据被加载到内存中,排序成为 Linq To Objects 的任务

于 2012-08-31T14:37:03.750 回答
0

看看https://stackoverflow.com/a/5971677/292787

您可以定义一个自定义方法...,并告诉 Entity Framework 如何将该方法转换为 SQL

于 2014-01-20T14:48:48.073 回答
0

我最近不得不解决这个问题。诀窍是对大多数语句(Math.Pow 除外)使用 System.Data.Entity.SqlServer 中的 SqlFunctions 而不是 System.Math。

备用 LINQ 样式(from/where/let/orderby 等)很有用,因为 let 关键字允许您分解问题并保持可读性。

var closestLocation = await (
    from q in qryable
    where q.LAT.HasValue && q.LONG.HasValue
    // Convert derees to radians (pi / 180 = 0.01745...)
    let dbLatitudeRadians = q.LAT.Value * 0.0174532925199433
    let dbLongitudeRadians = q.LONG.Value * 0.0174532925199433
    let requestLatitudeRadians = requestLatitude * 0.0174532925199433
    let requestLongitudeRadians = requestLongitude * 0.0174532925199433
    let deltaLatitudeRadians = requestLatitudeRadians - dbLatitudeRadians
    let deltaLongitudeRadians = requestLongitudeRadians - dbLongitudeRadians
    let sinHalfLatitudeDistance = SqlFunctions.Sin(deltaLatitudeRadians / 2) ?? 0.0
    let sinHalfLongitudeDistance = SqlFunctions.Sin(deltaLongitudeRadians / 2) ?? 0.0
    let cosThisLatitude = SqlFunctions.Cos(dbLatitudeRadians) ?? 0.0
    let cosThatLatitude = SqlFunctions.Cos(requestLatitudeRadians) ?? 0.0
    let expr = Math.Pow(sinHalfLatitudeDistance, 2) + cosThisLatitude * cosThatLatitude * Math.Pow(sinHalfLongitudeDistance, 2)
    let sqrtExpr = Math.Pow(expr, 0.5)
    let sqrt1MinusExpr = Math.Pow(1 - expr, 0.5)
    let distanceInMeters = 6376500 * 2 * SqlFunctions.Atan2(sqrtExpr, sqrt1MinusExpr)
    orderby distanceInMeters
    select q
).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
于 2016-06-13T17:46:49.473 回答