SQL Server 2014 で Entity Framework 6.1 の DbGeography 型を使用しています。おそらく 100,000 個のエンティティの最も近い場所を見つける必要があります。以下のように 1 つずつ実行すると遅くなります。私が持っているのと同様の方法を使用することは可能ですか?以下ですが、一度にすべてを行いますか?
C#:
public List<GeocodableEntity> LinkToRoadNodes(List<GeocodableEntity> entities)
{
foreach (var entity in entities)
{
var nearestLocation = GetNearestLocation(entity.Latitude, entity.Longitude, DEFAULT_ROAD_NODE_LINK_RADIUS);
// update entity with values from nearestLocation
}
return entities;
}
private GeoLocation GetNearestLocation(float latitude, float longitude, double searchRadius)
{
var sourcePoint = Helper.CreateDbGeographyPoint(latitude, longitude);
return Locations.Where(x => x.Point.Distance(sourcePoint) < searchRadius)
.OrderBy(x => x.Point.Distance(sourcePoint))
.FirstOrDefault();
}
これを言う理由は、これより前に、ストアド プロシージャを使用して同様のことを行っていたからです。
SQL で同様:
ALTER PROCEDURE [dbo].[GetNearestLocationNodesByCoordinates]
@CoordinateList dbo.CoordinateListWithRefId READONLY
AS
BEGIN
WITH InputCTE AS
(
SELECT RefID, geography::Point(Latitude, Longitude, 4326) AS Point
FROM @CoordinateList
)
SELECT x.RefID, x.NodeId, x.Latitude, x.Longitude, x.LocationTypeId
FROM (SELECT I.RefID as 'RefID',
L.NodeId,
L.Point.Lat as 'Latitude',
L.Point.Long as 'Longitude',
L.LocationTypeId,
ROW_NUMBER() OVER (PARTITION BY I.RefID ORDER BY L.Point.STDistance(I.Point)) AS Ranking
FROM InputCTE AS I
JOIN Location AS L
ON L.Point.STDistance(I.Point) <= 5000) AS x WHERE Ranking = 1
END
@CoordinateList の場所:
CREATE TYPE [dbo].[CoordinateListWithRefId] AS TABLE(
[RefID] [int] NOT NULL,
[Latitude] [float] NOT NULL,
[Longitude] [float] NOT NULL
)
可能であれば、ストアド プロシージャに触れたり、SQL クエリ リテラルを入力したりせずに、C# コードで同じことを行いたいと考えています。
並列 Foreach :
タイプ 'System.InvalidOperationException' の例外が EntityFramework.dll で発生しましたが、ユーザー コードで処理されませんでした 追加情報: モデルの作成中はコンテキストを使用できません。この例外は、コンテキストが OnModelCreating メソッド内で使用されている場合、または同じコンテキスト インスタンスが複数のスレッドによって同時にアクセスされている場合にスローされる可能性があります。DbContext および関連するクラスのインスタンス メンバーは、スレッド セーフであることが保証されていないことに注意してください。