Web Api 2 - 转换值并合并子查询中的值
问题描述:
在使用EF的Web API 2项目中,我试图让控制器返回数据库中的项目列表。这很简单。 问题来了,当我想要它返回一个单一的坐标值,从一个函数计算,下面,根据位置列表。 所有方法都会根据地理位置值列表计算中心点。该方法按预期工作。什么不起作用,是控制器的行为。Web Api 2 - 转换值并合并子查询中的值
-
运行下面的代码,导致
“LINQ实体不 识别方法‘双ToDouble(System.String)’方法,和 这种方法不能被翻译成存储表达。'
我目前使用的
item.Locations.FirstOrDefault().cX
,我知道它不会工作,因为它总是会返回相同的值。但是item.cX
不起作用。那么,我应该如何使用我的陈述 按预期工作?
代码
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);
}
答
尝试是这样的:
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();
}
你试过double.Parse(item.Locations.FirstOrDefault()CX),而不是Convert.Double(item.Locations.FirstOrDefault ().CX)? –
ToDouble无法转换为SQL - EF会尝试将整个IQueryable部分转换为一个SQL查询;那么它就会失败,因为在SQL中转换是不可能的。你将不得不使用db.Items.ToList()...来完成这个任务。 – DevilSuichiro
@ChrisBartlett是的,同样的结果。 – brother