【问题标题】:Web Api 2 - converting values and combine values from sub queryWeb Api 2 - 转换值并合并来自子查询的值
【发布时间】:2018-04-24 02:44:01
【问题描述】:

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

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

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

  2. 我目前正在使用item.Locations.FirstOrDefault().cX,我 知道不会起作用,因为它总是会返回相同的值。但 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);
    }

【问题讨论】:

  • 你试过用 double.Parse(item.Locations.FirstOrDefault().cX) 代替 Convert.Double(item.Locations.FirstOrDefault().cX) 吗?
  • ToDouble 无法转换为 SQL - EF 将尝试将整个 IQueryable 部分转换为一个 SQL 查询;它失败了,因为在 SQL 中无法进行转换。你必须使用 db.Items.ToList()... 来完成这个任务。
  • @ChrisBartlett 是的,结果相同。
  • @DevilSuichiro 我知道它不会像现在这样工作 - 但我不确定如何修改我的代码以使其工作 - 因此我的问题:-)

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


【解决方案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();
}

【讨论】:

    猜你喜欢
    • 2020-06-19
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多