Linq到SQL和SQL地理类型

本文关键字:SQL 类型 Linq | 更新日期: 2023-09-27 18:21:49

是否有任何方法可以在Visual Studio 2012中使用LINQ to SQL映射到SQL地理类型?我需要能够将SQL地理类型插入数据库中,并查询SQL地理类型。我已经提到了这个链接,但它似乎没有解决我的问题。

Linq到SQL和SQL地理类型

LINQ to SQL本机不支持您已经讨论过的SQL地理类型。要解决此问题,请结合使用数据库中的视图、存储过程和计算列。简而言之:

  • 在将地理数据类型转换为varbinary的表中包含或添加计算列。LINQ to SQL可以将此计算列映射到字节数组
  • 为每个将具有地理数据的表创建视图,但不包含不支持的地理数据类型列
  • 使用LINQ to SQL查询中的视图,而不是原始表
  • 要插入或更新地理数据,请使用存储过程或原始SQL查询来执行这些操作

以下是步骤的说明(未经测试!):

创建表格:例如

CREATE TABLE Locations (
    Id INT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(50) NOT NULL,
    Location GEOGRAPHY NOT NULL,
    LocationVarbinary AS CAST(Location AS VARBINARY(MAX))
)

注:如果您想要的表已经存在,请使用本机SQL添加地理位置和计算列。

基于所需的表创建视图,但不包括不支持的地理数据类型列:例如

CREATE VIEW LocationsView AS
SELECT Id, Name, Location.Lat AS Latitude, Location.Long AS Longitude
FROM Locations

在LINQ to SQL查询中使用这些视图,而不是表:例如

var db = new MyDataContext();
var locations = from l in db.LocationsView
                select l;

要插入或更新地理数据,请使用存储过程或原始SQL查询来执行插入或更新。例如

CREATE PROCEDURE InsertLocation
    @Name NVARCHAR(50),
    @Latitude FLOAT,
    @Longitude FLOAT
AS
BEGIN
    DECLARE @Location GEOGRAPHY = geography::Point(@Latitude, @Longitude, 4326)
    INSERT INTO Locations (Name, Location)
    VALUES (@Name, @Location)
END

从C#代码调用存储过程:例如

var db = new MyDataContext();
db.InsertLocation("New Location", 47.65100, -122.34900);

要使用地理数据(例如获取距离内的位置),请结合使用SQL Server地理数据类型中的SqlFunctions类和STDistance方法。例如

var db = new MyDataContext();
var point = DbGeography.FromText("POINT(-122.34900 47.65100)");
var distance = 1000; // meters
var locations = from l in db.LocationsView
                where SqlFunctions.DataLength(l.LocationVarbinary) > 0
                let location = DbGeography.FromBinary(l.LocationVarbinary)
                where location.Distance(point) <= distance
                select l;

此查询应返回LocationsView中位置列位于指定点 1000米范围内的所有行

注:DbGeography.FromBinary无法处理NULL值,因此SqlFunctions.DataLength(l.LocationVarbinary) > 0筛选出长度为0的LocationVarbinary行(即计算出的源Location列为NULL的行)。