6

使用实体框架,我正在尝试像这样连接两个表。

...
join f in ent.FTypes on Int32.Parse(c.CourseID[0].ToString()) equals f.FTypeID
...

字符串 CourseID 的第一个字符是数字,FTypeID 是 int。

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

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

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

join FType f on SUBSTRING(c.CourseID, 1, 1) = f.FTypeID

有没有人有解决方案必须在 LINQ to Entities 中执行此操作?

4

2 回答 2

5

这是一个相当讨厌的连接,但我在 Entity Framework 中使用类似的数据进行了一些测试,并得出了一些你可以在你的数据上进行测试的东西。

它用于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()

它生成如下所示的 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))

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

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


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

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

于 2013-06-03T15:33:57.243 回答
0

我不确定这在 8 年前是否有效,但现代EF6实现允许您添加匿名类型,因此您可以将转换添加到初始选择语句,然后您可以直接在联接中比较新属性。

    from c in ent.Courses
    select new { typeId = c.CourseId.Substring(0, 1), c }
    join f in ent.FTypes.Select(t => new { stringId = 
    t.FTypeId.ToString(), t }
    on c.typeId equals f.stringId into ...

注意: join 语句似乎不支持 ToString(),但 select 语句支持。

您也可以将 CouresId.Substring 移动到 join 语句中,但这可能会降低运行效率。

在 SQL 中的结果是这样的:

INNER JOIN [ent].[FTypes] AS [Extent2] ON 
(LTRIM(RTRIM(SUBSTRING([Extent1].[nvarchar(max)], 3 + 1, 1)))) =  
CAST([Extent2].[Id] AS nvarchar(max))
于 2021-06-17T18:03:38.593 回答