【问题标题】:How do I get a spatial value from EF Core's FromSqlRaw如何从 EF Core 的 FromSqlRaw 获取空间值
【发布时间】:2021-01-30 16:29:24
【问题描述】:

最近我遇到了一个问题,我只需要使用 FromSqlRaw 到我的数据库来执行 Postgresql 扩展之一的功能。这个函数返回一个条目,我想以某种方式获取这个条目的值。但是,由于某些原因,我不能这样做:

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}

【问题讨论】:

  • "我不能这样做" => 请说明:您是否收到编译错误?例外?什么信息?
  • 哪个值?...
  • 我收到 42601 语法错误(在“d”处或附近),它显示我的查询为:{select ld."Geom", ST_Buffer(ld."Geom", 100, 'join= mitre') 来自 public."Layers" ld where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb 和 ld."OId" = 3126}
  • ST_Buffer的值(ld.\"Geom\", 100, 'join=mitre'),是返回数据库入口st_buffer的函数(MULTIPOLYGON(((一些坐标))))跨度>
  • 首先,在问题本身中发布实际的错误文本。

标签: c# asp.net postgresql linq postgis


【解决方案1】:

您使用字符串插值生成导致无效查询的查询字符串。

... where ld."LId" = f21e400c-9e6d-4c28-b14c-1f0ced5b6ebb 

代码创建了一个带有注入值的 SQL 字符串,而不是参数化查询,从而导致无效查询。

FromSqlRaw 适用于普通字符串和明确指定的参数。事实上,文档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 类。

读取 GIS 类型

ST_Buffer 是 PostgreSQL 和 MySQL 使用的标准 GIS 函数,它返回空间类型。在 SQL Server 中,它是 STBuffer。

空间类型are supported in EF Core 通过NetTopologySuite 包和文档中提到的特定于数据库的包。

对于 PostgreSQL,正确的包是 Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite。 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();

【讨论】:

  • 好吧,事实并非如此。我在另一个查询中使用了同样的东西,它工作得很好。 LId 是 GUID,不是字符串,layerId 也是 GUID 类型,所以它再次起作用。
  • @Aldres 就是这样。看看执行的查询是什么样子的。您运行不同的查询
  • @Aldres 为什么不在字符串中使用 FromSqlInterpolated without 连接?还是带有显式参数的 FromSqlRaw?
  • 啊,我忘记了一次引号,但这并不能真正回答我的主要问题,我的错误,对不起,谢谢!。那么,如果我的 LayerData 实体中没有这样的列,我该如何从这个查询中猜出这个 ST_Buffer 呢?
  • @Aldres 再多的引用也无法修复动态 SQL 中的漏洞。解决方案是使用参数化查询。您发布的错误是关于无效查询,而不是 ST_Buffer 函数
猜你喜欢
  • 2020-11-23
  • 1970-01-01
  • 2021-03-06
  • 2022-01-14
  • 1970-01-01
  • 2021-04-07
  • 2021-10-13
  • 1970-01-01
  • 2022-08-21
相关资源
最近更新 更多