Web Api 2 - 转换值并合并来自子查询的值
Web Api 2 - converting values and combine values from sub query
在 Web API 2 项目中,使用 EF,我正在尝试让控制器return 数据库中的项目列表。就这么简单。
问题来了,当我想让它 return 一个单一的坐标值时,它是根据一个位置列表从下面的函数计算出来的。
该方法所做的全部工作是根据 GeoLocation 值列表计算中心点。该方法按预期工作。什么不起作用,是控制器动作。
运行 下面的代码,结果是
'LINQ to Entities 不
识别方法 'Double ToDouble(System.String)' 方法,并且
此方法无法转换为存储表达式。'
我目前正在使用 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();
}
在 Web API 2 项目中,使用 EF,我正在尝试让控制器return 数据库中的项目列表。就这么简单。 问题来了,当我想让它 return 一个单一的坐标值时,它是根据一个位置列表从下面的函数计算出来的。 该方法所做的全部工作是根据 GeoLocation 值列表计算中心点。该方法按预期工作。什么不起作用,是控制器动作。
运行 下面的代码,结果是
'LINQ to Entities 不 识别方法 'Double ToDouble(System.String)' 方法,并且 此方法无法转换为存储表达式。'
我目前正在使用
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();
}