如何从 EF Core 的 FromSqlRaw 获取空间值
How do I get a spatial value from EF Core's FromSqlRaw
最近我遇到了一个问题,我只需要对我的数据库使用 FromSqlRaw 来执行 Postgresql 扩展之一的功能。此函数 returns 是一个条目,我想以某种方式获取此条目的值。但是,由于某些原因我不能这样做:
var buffer = DataContext.LayerDatas.FromSqlRaw($"select ST_Buffer(ld.\"Geom\", 100, 'join=mitre') " +
$"from public.\"Layers\" ld where ld.\"LId\" = {layerId} and ld.\"OId\" = {objectId}").FirstOrDefault();
从 SqlRaw 获取计算值以便在我的代码中使用它的正确方法是什么?
编辑:
当我通过 DBeaver 执行查询时,它会给我以下信息:
我想在我的 C# 代码中获取它。
但是 c# 应用程序中的代码给出了以下异常:
42601 syntax error (at or near "d"),
它显示我的查询为:
{select ld."Geom", ST_Buffer(ld."Geom", 100, 'join=mitre') from public."Layers" ld where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb and ld."OId" = 3126}
您使用了字符串插值来生成导致查询无效的查询字符串。
... where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb
代码创建了一个 SQL 字符串,而不是参数化查询,其中包含导致无效查询的注入值。
FromSqlRaw works with normal strings and explicitly specified parameters. In fact, the docs have a pretty big warning about this.
在 FromSqlRaw 中使用参数
要使用 FromSqlRaw
,必须 不能使用 插值。参数可以按位置传递:
var sql="select ST_Buffer(ld.Geom, 100, 'join=mitre')
from public.Layers ld
where ld.LId = {0} and ld.OId = {1}";
var buffer = DataContext.LayerDatas.FromSqlInterpolated(sql,layerId,objectId)
.FirstOrDefault();
C# 允许多行字符串,因此无需使用串联来提高查询的可读性。
通过 FromSqlInterpolated
使用插值
如果你想使用插值传递参数你需要FromSqlInterpolated :
var buffer = DataContext.LayerDatas.FromSqlInterpolated(
$"select ST_Buffer(ld.Geom, 100, 'join=mitre')
from public.Layers ld
where ld.LId = {layerId} and ld.OId = {objectId}"
).FirstOrDefault();
请注意,该字符串是 一个没有串联的长字符串。这会产生 FromSqlInterpolated
.
预期的 FormattableString class
读取 GIS 类型
ST_Buffer 是 PostgreSQL and MySQL which returns a spatial type. In SQL Server it's STBuffer 使用的标准 GIS 函数。
空间类型 are supported in EF Core through the NetTopologySuite 包和文档中提到的 database-specific 包。
对于 PostgreSQL,正确的包是 Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite. Its use is explained in Spatial Mapping with NetTopologySuite
要与 EF Core 一起使用,安装正确的包后,需要在配置 DbContext 时注册它,例如:
options.UseSqlServer(
@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=WideWorldImporters",
x => x.UseNetTopologySuite());
之后,空间类型和属性可以像其他类型一样使用:
// Find the nearest city
var nearestCity = db.Cities
.OrderBy(c => c.Location.Distance(currentLocation))
.FirstOrDefault();
最近我遇到了一个问题,我只需要对我的数据库使用 FromSqlRaw 来执行 Postgresql 扩展之一的功能。此函数 returns 是一个条目,我想以某种方式获取此条目的值。但是,由于某些原因我不能这样做:
var buffer = DataContext.LayerDatas.FromSqlRaw($"select ST_Buffer(ld.\"Geom\", 100, 'join=mitre') " +
$"from public.\"Layers\" ld where ld.\"LId\" = {layerId} and ld.\"OId\" = {objectId}").FirstOrDefault();
从 SqlRaw 获取计算值以便在我的代码中使用它的正确方法是什么?
编辑:
当我通过 DBeaver 执行查询时,它会给我以下信息:
我想在我的 C# 代码中获取它。
但是 c# 应用程序中的代码给出了以下异常:
42601 syntax error (at or near "d"),
它显示我的查询为:
{select ld."Geom", ST_Buffer(ld."Geom", 100, 'join=mitre') from public."Layers" ld where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb and ld."OId" = 3126}
您使用了字符串插值来生成导致查询无效的查询字符串。
... where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb
代码创建了一个 SQL 字符串,而不是参数化查询,其中包含导致无效查询的注入值。
FromSqlRaw works with normal strings and explicitly specified parameters. In fact, the docs have a pretty big warning about this.
在 FromSqlRaw 中使用参数
要使用 FromSqlRaw
,必须 不能使用 插值。参数可以按位置传递:
var sql="select ST_Buffer(ld.Geom, 100, 'join=mitre')
from public.Layers ld
where ld.LId = {0} and ld.OId = {1}";
var buffer = DataContext.LayerDatas.FromSqlInterpolated(sql,layerId,objectId)
.FirstOrDefault();
C# 允许多行字符串,因此无需使用串联来提高查询的可读性。
通过 FromSqlInterpolated
使用插值如果你想使用插值传递参数你需要FromSqlInterpolated :
var buffer = DataContext.LayerDatas.FromSqlInterpolated(
$"select ST_Buffer(ld.Geom, 100, 'join=mitre')
from public.Layers ld
where ld.LId = {layerId} and ld.OId = {objectId}"
).FirstOrDefault();
请注意,该字符串是 一个没有串联的长字符串。这会产生 FromSqlInterpolated
.
读取 GIS 类型
ST_Buffer 是 PostgreSQL and MySQL which returns a spatial type. In SQL Server it's STBuffer 使用的标准 GIS 函数。
空间类型 are supported in EF Core through the NetTopologySuite 包和文档中提到的 database-specific 包。
对于 PostgreSQL,正确的包是 Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite. Its use is explained in Spatial Mapping with NetTopologySuite
要与 EF Core 一起使用,安装正确的包后,需要在配置 DbContext 时注册它,例如:
options.UseSqlServer(
@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=WideWorldImporters",
x => x.UseNetTopologySuite());
之后,空间类型和属性可以像其他类型一样使用:
// Find the nearest city
var nearestCity = db.Cities
.OrderBy(c => c.Location.Distance(currentLocation))
.FirstOrDefault();