Web Api 2 - 转换值并组合子查询中的值

时间:2017-11-10 19:44:56

标签: c# entity-framework linq asp.net-web-api asp.net-web-api2

在Web API 2项目中,使用EF,我试图让控制器返回数据库中的项目列表。那很简单。 当我希望它根据位置列表返回从下面的函数计算的单个坐标值时,问题就来了。 所有方法都是基于GeoLocation值列表计算中心点。该方法按预期工作。什么不起作用,是控制器动作。

  1. 运行以下代码,结果为

    'LINQ to Entities没有     识别方法'Double ToDouble(System.String)'方法,和     此方法无法转换为商店表达式。'

  2. 我目前正在使用item.Locations.FirstOrDefault().cX,我 知道将无法工作,因为它将始终返回相同的值。但 item.cX不起作用。那么我该怎么用才能做出我的陈述 按计划工作?

  3. 代码

    IdentityModel:

    public System.Data.Entity.DbSet<myModel.Item> Items { get; set; }
    

    型号:

    public class Item
    {
        public int Id { get; set; }
            public string Title { get; set; }
        public virtual ICollection<Location> Locations { get; set; }
    }
    
    public class ItemDTO
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public IEnumerable<GeoCoordinate> Coordinates { get; set; }
    }
    
    public class Location
    {
        public int Id { get; set; }
        public string cX { get; set; }
        public string cY { get; set; }
        public virtual Item Item { get; set; }
    }   
    

    控制器:

    [EnableQuery()]
        public IQueryable<GeoCoordinate> GetList()
        {
            var items = db.Items
                .Select(item => new ItemDTO()
                {
                    Id = item.Id,
            Title = item.Title
                    Coordinates = item.Locations
                        .Select(LocationsItem => new GeoCoordinate() //System.Device.Location
                        {
                            Latitude = Convert.ToDouble(item.Locations.FirstOrDefault().cX),
                            Longitude = Convert.ToDouble(item.Locations.FirstOrDefault().cY)
                        })
                        .ToList()
                })
                .AsEnumerable()
                .Select(fetchedItem => GetCentralGeoCoordinate(fetchedItem.Coordinates));
    
            return items.AsQueryable();
        }
    

    GetCentralGeoCoordinate功能:

    public static GeoCoordinate GetCentralGeoCoordinate(IEnumerable<GeoCoordinate> geoCoordinates)
        {
            if (geoCoordinates.Count() == 1)
            {
                return geoCoordinates.Single();
            }
    
            double x = 0;
            double y = 0;
            double z = 0;
    
            foreach (var geoCoordinate in geoCoordinates)
            {
                var latitude = geoCoordinate.Latitude * Math.PI / 180;
                var longitude = geoCoordinate.Longitude * Math.PI / 180;
    
                x += Math.Cos(latitude) * Math.Cos(longitude);
                y += Math.Cos(latitude) * Math.Sin(longitude);
                z += Math.Sin(latitude);
            }
    
            var total = geoCoordinates.Count();
    
            x = x / total;
            y = y / total;
            z = z / total;
    
            var centralLongitude = Math.Atan2(y, x);
            var centralSquareRoot = Math.Sqrt(x * x + y * y);
            var centralLatitude = Math.Atan2(z, centralSquareRoot);
    
            return new GeoCoordinate(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
        }
    

1 个答案:

答案 0 :(得分:1)

尝试这样的事情:

public IQueryable<GeoCoordinate> GetList()
{
    // this ToList fetches the data from the db. 
    // now you don't have to worry about convert inside EF
    var sourceItems = db.Items.Include(x => x.Locations).ToList(); 

    // Select updated to answer part 2 (I believe).
    var items = sourceItems.Select(item => new ItemDTO()
        {
            Id = item.Id,
            Title = item.Title
            Coordinates = item.Locations
                .Select(itemLocation => new GeoCoordinate()
                {
                    Latitude = Convert.ToDouble(itemLocation.cX),
                    Longitude = Convert.ToDouble(itemLocation.cY)
                })
        })
        .AsEnumerable()
        .Select(fetchedItem => GetCentralGeoCoordinate(fetchedItem.Coordinates));

    return items.AsQueryable();
}