使用Entity Framework,我正在尝试加入两个这样的表。
...
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中执行此操作?
答案 0 :(得分:3)
这是一个相当令人讨厌的联接,但我在实体框架中做了一些类似数据的测试,并得出了你可以测试的东西。
它使用string.Substring
从字符串操作数中获取第一个字符,然后使用仅EF方法SqlFunctions.StringConvert
的组合(这些方法可在System.Data.Objects.SqlClient中找到)对于整数操作数,使用强制转换为double
1 ,最后为string.Trim
2 。
我已对此进行了测试并确认至少在EF 4中支持所有函数。问题中提出或推荐的其他几种方法都不起作用,因为Entity Framework不知道如何将它们转换为适当的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 需要修剪结果字符串,因为字符串转换会产生一些多余的填充。
答案 1 :(得分: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))