I cant make Linq compare geodistances?

穿精又带淫゛_ 提交于 2019-12-11 06:46:20

问题


Im getting the error:

'new GeoCoordinate(MyEntity.Lat, MyEntity.Lon).GetDistanceTo(14.4416616666667, 5.71794583333333)' is not supported in a 'Where' Mobile Services query expression.

From the following query:

GeoCoordinate mypos = new GeoCoordinate(MainPage.myEntity.Lat, MainPage.myEntity.Lon);

var items = await App.MobileService
                        .GetTable<MyEntity>()
                        .Where(MyEntity => MyEntity.Id != MainPage.myEntity.Id && MyEntity.IsSelected == MainPage.myEntity.IsSelected 
                            && (MyEntity.Lat != 0 && MyEntity.Lon != 0) 
                            && new GeoCoordinate(MyEntity.Lat, MyEntity.Lon).GetDistanceTo(mypos) <= 5000)
                        .Take(20)
                        .ToListAsync();

I'm trying to get 20 entities from a table that is not me and within 5 km of my position.


回答1:


One thing you need to be aware is that the line expression is not executed locally. It's instead translated into a query string which is sent to the server - otherwise you'd be downloading a lot more data than you need (which you still can do, by the way). Given that, there's no way to translate the method GeoCoordinate.GetDistanceTo into something which can be sent over the wire.

There are some operations which are supported in the server, such as arithmetic (+, -, *, /), and you could potentially implement something similar to what you need. Something like the code below should work (haven't tried it yet). Notice that you'll need to do the conversion between distance in coordinates (lat / lon) and whatever unit is returned by the GetDistanceTo method.

GeoCoordinate mypos = new GeoCoordinate(MainPage.myEntity.Lat, MainPage.myEntity.Lon);
double maxDistance = 1;
var items = await App.MobileService
    .GetTable<MyEntity>()
    .Where(e => e.Id != MainPage.myEntity.Id &&
                e.IsSelected == MainPage.myEntity.IsSelected &&
                (e.Lat != 0 && e.Lon != 0) &&
                ( ((e.Lat - mypos.Lat) * (e.Lat - mypos.Lat) +
                   (e.Lon - mypos.Lon) * (e.Lon - mypos.Lon)) < maxDistance )
    .Take(20)
    .ToListAsync();

Or, another alternative as I mentioned before would be to simply not to filter by the distance on that call, and filter it afterwards. Something like the code below:

GeoCoordinate mypos = new GeoCoordinate(MainPage.myEntity.Lat, MainPage.myEntity.Lon);
List<MyEntity> items = new List<MyEntity>();
int skip = 0;
while (items.Count < 20) {
    var temp = await App.MobileService
        .GetTable<MyEntity>()
        .Where(e => e.Id != MainPage.myEntity.Id &&
                    e.IsSelected == MainPage.myEntity.IsSelected &&
                    (e.Lat != 0 && e.Lon != 0)
        .Skip(skip)
        .Take(20)
        .ToListAsync();
    if (temp.Count == 0) break;
    foreach (var item in temp)
    {
        if (new GeoCoordinate(item.Lat, item.Lon).GetDistanceTo(mypos) <= 5000)
        {
            items.Add(item);
        }
    }
}


来源:https://stackoverflow.com/questions/14362724/i-cant-make-linq-compare-geodistances

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!