上で提案されたように、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