0

我有两个数据库表映射到我的 MVC 应用程序中的模型:

public class BuildingLocation
{
    public int id { get; set; }
    public double Lat { get; set; }
    public double Lng { get; set; }
}

public class Building
{
    public int id { get; set; }
    public string title { get; set; }
    //OTHER STUFF
}

使用 Linq / Entities,我试图获取建筑物列表,按与地图上给定点的距离排序。

DefaultConnection db = new DefaultConnection();    

 public IEnumerable<dynamic> GetBuildings(double north, double south, double east, double west)
    {
        double centreX = (east - west) / 2;
        double centreY = (north - south) / 2;
        var query = from b in db.Building
                    join l in db.BuildingLocation on
                    b.id equals l.id
                    select new {b.id, b.title, l.Lat, l.Lng,
                            dist = Math.Sqrt(((centreX - l.Lat) * (centreX - l.Lat)) + ((centreY - l.Lng) * (centreY - l.Lng)))
                    };

        query = query.Where(l => l.Lat > west);
        query = query.Where(l => l.Lat < east);
        query = query.Where(l => l.Lng > south);
        query = query.Where(l => l.Lng < north);
        query = query.OrderBy(c => c.dist);
        return query.AsEnumerable();
       }

所以,显然这根本行不通。我以前从未使用过Linq。如何根据计算设置 OrderBy?

4

3 回答 3

1

尝试这个 :

public IEnumerable<dynamic> GetBuildings(double north, double south, double east, double west)
{
    double centreX = (east - west) / 2;
    double centreY = (north - south) / 2;
    var query = db.Building.Join(db.BuildingLocation.Where(l=> 
                             l.Lat > west &&  l.Lat < east 
                             && l.Lng > south && l.Lng < north), 
                             b => b.id , l => l.id, 
                             (b,l) => new {
                                            ID = b.id,
                                            Title = b.title,
                                            Lat = l.lat,
                                            Lng = l.Lng,
                                            dist =  Math.Sqrt(((centreX - l.Lat) * (centreX - l.Lat)) + ((centreY - l.Lng) * (centreY - l.Lng)))
                                          }).OrderBy(Q=>Q.dist);

    return query;
}

上面的查询是用 lambda 表达式编写的。如果您希望在查询表达式中使用此代码,请使用以下代码:

var query =  from result in (from b in db.Building
                join l in db.BuildingLocation on
                b.id equals l.id
                where l.Lat > west &&  l.Lat < east && l.Lng > south && l.Lng < north
                select new {b.id, b.title, l.Lat, l.Lng,
                        dist = Math.Sqrt(((centreX - l.Lat) * (centreX - l.Lat)) + ((centreY - l.Lng) * (centreY - l.Lng))) })
                order by result.dist select result;

这将解决您的问题。

于 2012-08-29T16:40:27.853 回答
1

如果您使用实体框架,您可能会收到以下异常消息:

“LINQ to Entities 无法识别方法 'Double Sqrt(Double)' 方法,并且此方法无法转换为存储表达式。”

所以我会分两步解决这个问题,内部查询应该只从表中获取数据,而在外部(现在是内存查询)中将进行距离计算和排序:

double centreX = (east - west) / 2;
double centreY = (north - south) / 2;

var query = (from result in
                ((from b in db.Building
                    join l in db.BuildingLocation on b.id equals l.id
                    where l.Lat > west && l.Lat < east && l.Lng > south && l.Lng < north
                    select new { b.id, b.title, l.Lat, l.Lng }).AsEnumerable()
                )
            select new
            {
                id = result.id,
                title = result.title,
                Lat = result.Lat,
                Lng = result.Lng,
                dist = Math.Sqrt(((centreX - l.Lat) * (centreX - l.Lat)) + ((centreY - l.Lng) * (centreY - l.Lng)))
            }).OrderBy(e => e.dist); 
于 2012-08-29T17:49:28.583 回答
0

在我的帽子顶部,只是为了建筑物,我会做这样的事情:

public IEnumerable<Building> GetBuildings(double north, double south, double east, double west)
{
    double centreX = (east - west) / 2;
    double centreY = (north - south) / 2;

    db.BuildingLocation.Where(l => l.Lat > west && l.Lat < east && l.Lng > south && l.Lng < north)
        .Join(
            db.Building, 
            b => b.id, 
            l => l.id, 
            (l, b) =>  new {Building = b, l.Lat, l.Lng })
        .AsEnumerable()
        .OrderBy(l => Math.Sqrt(((centreX - l.Lat) * (centreX - l.Lat)) + ((centreY - l.Lng) * (centreY - l.Lng))))
        .Select(l => l.Building)
}

我假设它不起作用,因为距离计算无法转换为 SQL,所以我在 OrderBy 之前插入了 AsEnumerable 调用——这意味着过滤发生在数据库端,但排序发生在——内存与 Linq to Objects。

于 2012-08-29T16:43:55.360 回答