Web Api 2 - 转换值并合并来自子查询的值

Web Api 2 - converting values and combine values from sub query

在 Web API 2 项目中,使用 EF,我正在尝试让控制器return 数据库中的项目列表。就这么简单。 问题来了,当我想让它 return 一个单一的坐标值时,它是根据一个位置列表从下面的函数计算出来的。 该方法所做的全部工作是根据 GeoLocation 值列表计算中心点。该方法按预期工作。什么不起作用,是控制器动作。

  1. 运行 下面的代码,结果是

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

  2. 我目前正在使用 item.Locations.FirstOrDefault().cX,我 知道不会起作用,因为它总是 return 相同的值。但 item.cX 不起作用。那么我应该用什么来发表我的声明 按预期工作?

密码

身份模型:

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);
    }

尝试这样的事情:

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();
}