C# &引用;其中xxx不为空且xxx/2<;“4”字:&引用;“不为空”;似乎是在我手术后被处决的

C# &引用;其中xxx不为空且xxx/2<;“4”字:&引用;“不为空”;似乎是在我手术后被处决的,c#,sql-server,linq,entity-framework-6,C#,Sql Server,Linq,Entity Framework 6,这是我的实体框架linq请求(用户已经存在,我的纬度和经度是十进制的): IQueryable dbQuery=context.Set() .Where(e=>e.GeoLat!=null&&e.GeoLong!=null&&user.Latitude!=null&&user.Longitude!=null&&user.Longitude!=null) .Where(e=>DbGeography.PointFromText(“点(“+e.GeoLong+”“+e.GeoLat+”),4326)

这是我的实体框架linq请求(用户已经存在,我的纬度和经度是十进制的):

IQueryable dbQuery=context.Set()
.Where(e=>e.GeoLat!=null&&e.GeoLong!=null&&user.Latitude!=null&&user.Longitude!=null&&user.Longitude!=null)
.Where(e=>DbGeography.PointFromText(“点(“+e.GeoLong+”“+e.GeoLat+”),4326)
.Distance(DbGeography.PointFromText(“点”(“+user.Longitude+”“+user.Latitude+”),4326))
以下是生成的SQL请求的相关部分:

AND 
( 
  [Extent1].[GeoLat] IS NOT NULL 
) 
AND 
( 
  [Extent1].[GeoLong] IS NOT NULL 
) 
AND 
( 
  48,697161 
  /* @p__linq__1 */ 
  IS NOT NULL 
) 
AND 
( 
  2,189617 
  /* @p__linq__2 */ 
  IS NOT NULL 
) 
AND 
( 
  ( 
    geography::stpointfromtext(N'POINT(' + 
    CASE 
    WHEN ( 
        [Extent1].[GeoLong] IS NULL 
      ) 
      THEN 
      N'' 
      ELSE cast( [Extent1].[GeoLong] AS nvarchar(max)) 
    END 
    + N' ' + 
    CASE 
    WHEN ( 
        [Extent1].[GeoLat] IS NULL 
      ) 
      THEN 
      N'' 
      ELSE cast( [Extent1].[GeoLat] AS nvarchar(max)) 
    END 
    + N')', 4326).stdistance(geography::stpointfromtext(N'POINT(' + cast( 2.189617 AS nvarchar(max)) + N' ' + cast( 48.697161 AS nvarchar(max)) + N')', 4326))
  ) 
  < cast( 50 
  /* @p__linq__3 */ 
  * 1000 AS float) 
)
和
( 
[Extent1]。[GeoLat]不为空
) 
及
( 
[Extent1]。[GeoLong]不为空
) 
及
( 
48,697161 
/*@p_uulinq_uu1*/
不为空
) 
及
( 
2,189617 
/*@p__linq__2*/
不为空
) 
及
( 
( 
地理::stpointfromtext(N'POINT('+
案例
何时(
[Extent1]。[GeoLong]为空
) 
然后
N“
ELSE强制转换([Extent1][GeoLong]为nvarchar(最大))
结束
+N''+
案例
何时(
[Extent1]。[GeoLat]为空
) 
然后
N“
ELSE强制转换([Extent1][GeoLat]为nvarchar(最大))
结束
+stdistance(地理::stpointfromtext(N'POINT('+cast(2.189617为nvarchar(max))+N'+cast(48.697161为nvarchar(max))+N'),4326))
) 
以下是我得到的错误:

在执行用户定义的例程或聚合“地理”期间发生.NET Framework错误: System.FormatException:24141:输入的第7位应为数字。输入已被删除)

错误似乎告诉我POINT()中的经度和纬度值实际上是位置7=>空值处的空字符串(“)”。 我不明白为什么会出现这个错误,因为我告诉SQl只获取值不为NULL的行。看起来SQL甚至对值为NULL的行执行地理操作

你能帮我了解一下原因吗


我使用EF6。

SQL Server不会对
操作执行短路评估。您可以通过使用
运算符生成
IFNULL
语句来解决问题:

IQueryable<Event> dbQuery = context.Set<Event>()
.Where(e => e.GeoLat != null && e.GeoLong != null && 
            user.Latitude != null && user.Longitude != null)
.Where(e => 
  DbGeography.PointFromText(
      "POINT(" + (e.GeoLong ?? "1") + " " + (e.GeoLat ?? "1") + ")", 4326)
    .Distance(DbGeography.PointFromText(
      "POINT(" + (user.Longitude ?? "1") + " " + (user.Latitude ?? "1") + ")", 4326)
    ) < distanceKM * 1000)
IQueryable dbQuery=context.Set()
.其中(e=>e.GeoLat!=null&&e.GeoLong!=null&&
user.Latitude!=null&&user.Longitude!=null)
。其中(e=>
DbGeography.PointFromText(
“点(“+(e.GeoLong???“1”)+”+“(e.GeoLat???“1”)+”),4326)
.Distance(DbGeography.PointFromText(
“点(“+(用户.经度??“1”)+”+“(用户.纬度??“1”)+”),4326)
)
编辑:如果由于将
NULL
值转换为空字符串而出现问题,您可以尝试将其转换为任意整数值,例如1。因为另一个
Where
子句将过滤掉这些行,所以它们的计算并不重要,只要它不抛出任何错误

我知道,理想情况下,这些行首先会被排除在
地理操作之外,但令人惊讶的是,实现起来并不那么简单。最简单的方法是允许
geography
操作继续进行,然后放弃其结果


要真正防止它被执行,您需要弄清楚如何让LINQ查询在
子句时发出一个
大小写。

T-SQL不像C#那样执行快捷方式求值。
的所有部分都可能进行评估。(这不是一个答案,我不知道如何使用EF正确地编写它——但它确实解释了您看到的内容。)实际上,POINT()中的空字符串是问题所在。地理操作不应该在long/lat值为NULL的行上执行,但我不知道如何实现这一点!通过使用三元运算符x,我成功地做到了这一点?y:z,其中地理操作在y中。这样,只有当x为真(x->lat/long!=null)时才执行它们。
IQueryable<Event> dbQuery = context.Set<Event>()
.Where(e => e.GeoLat != null && e.GeoLong != null && 
            user.Latitude != null && user.Longitude != null)
.Where(e => 
  DbGeography.PointFromText(
      "POINT(" + (e.GeoLong ?? "1") + " " + (e.GeoLat ?? "1") + ")", 4326)
    .Distance(DbGeography.PointFromText(
      "POINT(" + (user.Longitude ?? "1") + " " + (user.Latitude ?? "1") + ")", 4326)
    ) < distanceKM * 1000)