如何在实体框架中对子字符串和整数产生联接?

Sam*_*emi 5 sql linq entity-framework

使用实体框架,我试图像这样联接两个表。

...
join f in ent.FTypes on Int32.Parse(c.CourseID[0].ToString()) equals f.FTypeID
...
Run Code Online (Sandbox Code Playgroud)

字符串CourseID的第一个字符是一个数字,FTypeID是一个i​​nt。

不过,这似乎不起作用。我收到的异常消息是:

LINQ to Entities无法识别方法'Int32 Parse(System.String)'方法,并且该方法无法转换为存储表达式。“} System.Exception {System.NotSupportedException}

我要复制的是等效的SQL字符串(工作正常):

join FType f on SUBSTRING(c.CourseID, 1, 1) = f.FTypeID
Run Code Online (Sandbox Code Playgroud)

有没有人有解决方案,必须在LINQ to Entities中做到这一点?

Ant*_*ram 5

这是一个相当糟糕的连接,但我在实体框架中用类似的数据做了一些测试,并得出了一些你可以在你的数据上测试的东西。

它用于string.Substring从字符串操作数中获取第一个字符,然后使用仅 EF 方法SqlFunctions.StringConvert(这些方法可在 System.Data.Objects.SqlClient 中找到)与强制转换为double1 的组合,最后为整数操作数使用string.Trim2 .

我已经对此进行了测试,并确认至少在 EF 4 中支持所有功能。问题中提出或推荐的其他几种方法不起作用,因为实体框架不知道如何将它们转换为适当的 SQL 等效项。

join f in ent.FTypes
on c.CourseID.Substring(0, 1) 
   equals SqlFunctions.StringConvert((double)f.FTypeID).Trim()
Run Code Online (Sandbox Code Playgroud)

它生成一个 SQL 连接,如下所示:

INNER JOIN [dbo].[FTypes] AS [Extent2] 
ON ((SUBSTRING([Extent1].[CourseID], 0 + 1, 1)) = (LTRIM(RTRIM(STR( CAST( [Extent2].[FTypeID] AS float)))))) 
OR ((SUBSTRING([Extent1].[CourseID], 0 + 1, 1) IS NULL) AND (LTRIM(RTRIM(STR( CAST( [Extent2].[FTypeID] AS float)))) IS NULL))
Run Code Online (Sandbox Code Playgroud)

因此,基于此,您可能希望根据需要进行一些额外的过滤。

试一试,看看这是否有助于解决问题。


1SqlFunctions.StringConvert强制转换为 double 是必要的,因为整数没有重载并且没有其他单个最佳匹配,所以我强制使用一个。

2生成的字符串需要修剪,因为字符串转换会产生一些多余的填充。

  • 这是一个很好的问题,值得考虑。这不会利用索引,但是,您在 SQL 中的原始查询也将至少错过某些优势。如果您担心,请在这方面进行一些分析,看看是否存在瓶颈。 (2认同)