正如上面建议的那样,添加 db.DoctorsPrivateClinics.AsEnumerable() 解决了我的问题。经过一点改进后,我的功能是解决方案:
double longitude=0;
double latitude=0;
var city = from c in db.Cities
where c.Code == Convert.ToInt32(Request.QueryString["Area"])
select c;
city = city.Take(1);//take the first value, that sould be the only value in this case
if (city.Count() == 0)
{
//hanlde error
}
else
{
City cit = city.First();
Calculations.GetLongitudeLatitudeGoogle getLongLat = new Calculations.GetLongitudeLatitudeGoogle();
getLongLat.GetLongitudeLatitude("", cit.Name, "", out longitude, out latitude);
}
var doctorPractise = from d in db.DoctorsPrivateClinics.AsEnumerable()//or .ToList()
where CalcualateDistance(Convert.ToDouble(d.PrivateClinic.Latitude), Convert.ToDouble(d.PrivateClinic.Longtitude), latitude, longitude)<5.0f
select d;
其中函数 CalcualateDistance 是:
{
/*
The Haversine formula according to Dr. Math.
http://mathforum.org/library/drmath/view/51879.html
dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2(sqrt(a), sqrt(1-a))
d = R * c
Where
* dlon is the change in longitude
* dlat is the change in latitude
* c is the great circle distance in Radians.
* R is the radius of a spherical Earth.
* The locations of the two points in
spherical coordinates (longitude and
latitude) are lon1,lat1 and lon2, lat2.
*/
double dDistance = Double.MinValue;
double dLat1InRad = Lat1 * (Math.PI / 180.0);
double dLong1InRad = Long1 * (Math.PI / 180.0);
double dLat2InRad = Lat2 * (Math.PI / 180.0);
double dLong2InRad = Long2 * (Math.PI / 180.0);
double dLongitude = dLong2InRad - dLong1InRad;
double dLatitude = dLat2InRad - dLat1InRad;
// Intermediate result a.
double a = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) +
Math.Cos(dLat1InRad) * Math.Cos(dLat2InRad) *
Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);
// Intermediate result c (great circle distance in Radians).
double c = 2.0 * Math.Asin(Math.Sqrt(a));
// Distance.
// const Double kEarthRadiusMiles = 3956.0;
const Double kEarthRadiusKms = 6376.5;
dDistance = kEarthRadiusKms * c;
return dDistance;
}
尽管这对我有用,但它不是使用 LINQ 的有效方法。所以我搜索了一个更好的解决方案,即在 T-SQL 中重新编写我的函数,因此改进的解决方案是:
double longitude=0;
double latitude=0;
var city = from c in db.Cities
where c.Code == Convert.ToInt32(Request.QueryString["Area"])
select c;
city = city.Take(1);//take the first value, that should be the only value in this case
if (city.Count() == 0)
{
//hanlde error
}
else
{
City cit = city.First();
Calculations.GetLongitudeLatitudeGoogle getLongLat = new Calculations.GetLongitudeLatitudeGoogle();
getLongLat.GetLongitudeLatitude("", cit.Name, "", out longitude, out latitude);
}
var doctorPractise = from d in db.DoctorsPrivateClinics
where db.CalculateDistance(Convert.ToDouble(d.PrivateClinic.Latitude), Convert.ToDouble(d.PrivateClinic.Longtitude), latitude, longitude) < 5.0f
select d;
用 T-SQL 写的函数在哪里:
ALTER FUNCTION PublicSiteDBUser.CalculateDistance
(
@latitudeArea float(53),
@longitudeArea float(53),
@latitudePractise float(53),
@longitudePractise float(53)
)
RETURNS float(53)
AS
BEGIN
DECLARE @dDistance as float(53)=0
DECLARE @dLat1InRad as float(53)=0
DECLARE @dLong1InRad as float(53)=0
DECLARE @dLat2InRad as float(53)=0
DECLARE @dLong2InRad as float(53)=0
DECLARE @dLongitude as float(53)=0
DECLARE @dLatitude as float(53)=0
DECLARE @a as float(53)=0
DECLARE @c as float(53)=0
DECLARE @kEarthRadiusKms as float(53)=6376.5
SET @dLat1InRad = @latitudeArea * PI() / 180.0
SET @dLong1InRad= @longitudeArea * PI()/180.0
SET @dLat2InRad= @latitudePractise * PI()/180.0
SET @dLong2InRad= @longitudePractise * PI()/180.0
SET @dLongitude = @dLong2InRad - @dLong1InRad
SET @dLatitude = @dLat2InRad - @dLat1InRad
SET @a = POWER(SIN(@dLatitude/2.0), 2.0)+COS(@dLat1InRad)*COS(@dLat2InRad) * POWER (SIN(@dLongitude/2.0),2.0)
SET @c = 2.0*ASIN(SQRT(@a))
SET @dDistance = @kEarthRadiusKms * @c
RETURN @dDistance
END