Linq生成没有选择的选择

时间:2018-07-11 13:20:16

标签: c# sql entity-framework linq

在sql中,我可以这样做

select 'a' as MyColumn

因此,我在linq中使用实体框架进行查询,该查询从数据库中获取一些数据,但是,我需要将该查询与一行合并,并且在sql中,我可以这样做:

select ... from ...
union 
select 'a' as MyColumn

如何使用linq生成此查询? 我尝试这样做:

var query = (from ... select new {..}).Union(new List<...> { new ...() { MyColumn = 'a' } })

但是我认为实体框架不知道如何将内存列表中的内容转换为sql

我需要获取一个IQueryable结果,而不是List或内存集合中的其他结果,因为将来我需要将该结果加入其他sql linq查询中。

1 个答案:

答案 0 :(得分:2)

这是不可能的,您不应该这样做。两者都有相同的原因:实体框架将尝试将整个LINQ语句转换为SQL,包括本地列表(new List<...>)。

之所以不可能,是因为EF无法将C#对象转换为SQL构造。

您不应该这样做的原因是它非常浪费:您使用C#代码构建列表,EF(如果可以)将其转换为SQL语句,数据库运行该SQL语句并将其转换为结果集,EF接收结果集并将其转换为您最初提供的列表。

只是为了演示它,我将展示如果您使用EF确实知道如何转换为SQL的原始值列表来执行此操作,

var ints = Enumerable.Range(1,5);
var res = Products.Select(c => c.Id).Union(ints).ToList();

这将产生以下SQL语句:

SELECT 
    [Distinct1].[C1] AS [C1]
    FROM ( SELECT DISTINCT 
        [UnionAll5].[ProductId] AS [C1]
        FROM  (SELECT 
            [Extent1].[ProductId] AS [ProductId]
            FROM [dbo].[Product] AS [Extent1]
        UNION ALL
            SELECT 
            1 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
        UNION ALL
            SELECT 
            2 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]
        UNION ALL
            SELECT 
            3 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable3]
        UNION ALL
            SELECT 
            4 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable4]
        UNION ALL
            SELECT 
            5 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll5]
    )  AS [Distinct1]

如您所见,EF为列表中的每个元素生成了一个SingleRowTable x条目,以使用实际查询的ID为UNION建立“临时表”。

结论:只需从数据库中查询所需内容,然后添加到结果中即可。这样做很容易:

(from ... select new {..})
    .AsEnumerable() // continue in memory
    .Union(...)