我正在尝试将一系列SqlGeometry值保存到SQL Server 2008数据库.基本上我在SQL Server存储过程中有一个tabletype,如下所示:CREATE TYPE [dbo].[TableType_Example] AS TABLE([SpatialID] [bigint] NOT NULL,[Recor...
我正在尝试将一系列SqlGeometry值保存到SQL Server 2008数据库.
基本上我在SQL Server存储过程中有一个tabletype,如下所示:
CREATE TYPE [dbo].[TableType_Example] AS TABLE
(
[SpatialID] [bigint] NOT NULL,
[RecordID] [bigint] NOT NULL,
[geom] [geometry] NOT NULL
)
然后我在C#中构建一个数据表并像这样发送:
public static bool SaveSpatialDataElements(long recordID, List<BOSpatial> featureList)
{
//Setup features datatable
DataTable dtFeatures = new DataTable();
dtFeatures.Columns.Add("SpatialID", typeof(SqlInt64));
dtFeatures.Columns.Add("RecordID", typeof(SqlInt64));
dtFeatures.Columns.Add("geom", typeof(SqlGeometry));
foreach(var curFeature in featureList)
{
object[] curRowObjects = new object[dtFeatures.Columns.Count];
curRowObjects[0] = curFeature.SpatialID;
curRowObjects[1] = recordID;
using (var reader = new StringReader(curFeature.ToGML()))
{
using (var xmlreader = new XmlTextReader(reader))
{
curRowObjects[2] = SqlGeometry.GeomFromGml(new SqlXml(xmlreader), 0);
}
}
DataRow row = dtFeatures.NewRow();
row.ItemArray = curRowObjects;
dtFeatures.Rows.Add(row);
}
DbConn conn = new DbConn();
conn.Connect();
conn.ExecuteStoredProcedure(false, "USP_tblSpatialLocation_Update", recordID, dtFeatures);
conn.Disconnect();
return true;
}
这适用于我所有其他数据表,但是这一个包含一个SqlGeometry列,它会出现错误消息:
An exception of type ‘System.ArgumentException’ occurred in
System.Data.dll but was not handled in user codeAdditional information: The type of column ‘geom’ is not supported.
The type is ‘SqlGeometry’
这对我没有任何意义,因为我在文档中阅读的内容似乎支持该数据类型.
有什么想法吗?
编辑:
下面的评论和我链接的文章:https://viswaug.wordpress.com/2008/09/29/inserting-spatial-data-in-sql-server-2008/似乎表明我需要将SqlGeometry的数据类型更改为SqlDbType.Udt.可悲的是,当我使用数据表时,我无法定义UdtTypeName =“GEOMETRY”;因为这是在参数上设置的.
解决方法:
由于对您的问题做了简短的评论,我有机会充分利用这些选项.看来目前(甚至尝试.NET 4.6和SQL 2014)在定义DataTable的列时,不能将SqlGeography或SqlGeometry设置为typeof()参数.为了绝对清晰,您可以在.NET中执行此操作甚至填充它,但您无法将该表作为TVP传递给存储过程.
有两种选择.
选项1.传递WKT格式的值.
定义您的表类型如下.
CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
[geom] [varchar](max) NOT NULL
)
然后按如下方式定义存储过程.
CREATE PROCEDURE [dbo].[BulkInsertFromWKT]
@rows [dbo].[WKT_Example] READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO [dbo].[Table1]
([SpatialData])
SELECT
geometry::STGeomFromText(R.[SpatialData], 4326)
FROM
@rows R;
END
按如下方式定义.NET DataTable:
DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));
填充如下:
for (int j = 0; j < geometryCollection.Count; j++)
{
System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();
wktTable.Rows.Add(wkt.ToString());
}
选项2.以WKB格式传递值.
定义您的表类型如下.
CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
[geom] [varbinary](max) NOT NULL
)
然后按如下方式定义存储过程.
CREATE PROCEDURE [dbo].[BulkInsertFromWKB]
@rows [dbo].[WKB_Example] READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO [dbo].[Table1]
([SpatialData])
SELECT
geometry::STGeomFromWKB(R.[SpatialData], 4326)
FROM
@rows R;
END
按如下方式定义.NET DataTable:
DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));
填充如下:
for (int j = 0; j < geometryCollection.Count; j++)
{
wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}
笔记:
按如下方式定义SqlParameter:
SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;
我从地理工作中留下了4326的SRID.您可以将其更改为您想要的任何内容 – 事实上,如果您使用地理位置,我建议您将其作为第二个参数来为您提供灵活性.
此外,如果性能至关重要,您会发现更好地使用WKB.我的测试发现WKB在WKT的45%到65%的时间内完成了WKB.这取决于数据的复杂程度和设置.
当您的存储过程具有[几何]或[地理]类型的参数时,您在将参数的UdtTypeName指定为“几何”/“地理”时找到的信息是正确的.它不适用于TVP.
本文标题为:c# – 包含SqlGeometry的数据表导致存储过程执行失败…为什么?
基础教程推荐
- C#中Dapper的使用教程 2023-04-22
- c# – EF4.1 – Fluent API – SqlQuery – 调用sproc时的配置映射 – 数据读取器与指定的实体类型不兼容 2023-11-23
- C# 图片与Base64码的相互转化问题(代码详解) 2023-02-08
- 可空类型Nullable<T>用法详解 2023-05-22
- linux centos 8 为.net core 添加进程守护 Supervisor 2023-09-27
- C#中Winform 实现Ajax效果自定义按钮 2022-12-01
- Unity 通过LineRenderer绘制两点之间的直线操作 2023-04-10
- C# 中的partial 关键字详解 2023-06-27
- 如何在C#中使用Dapper ORM 2023-04-10
- C#调用百度API实现活体检测的方法 2023-01-28