C# 如何方便地重写LINQ查询?

C# 如何方便地重写LINQ查询?,c#,.net,sql-server,linq,entity-framework,C#,.net,Sql Server,Linq,Entity Framework,我意识到SQL Server无法有效地处理一些基本SQL查询,例如: SELECT TOP (1) [t0].[Id], [t0].[L1], [t0].[L2], [t0].[Value] FROM [Foos] AS [t0] INNER JOIN [Lookup1] AS [t1] ON [t1].[Id] = [t0].[L2] INNER JOIN [Lookup2] AS [t2] ON [t2].[Id] = [t0].[L1] WHERE ([t1].[Name] = 'a')

我意识到SQL Server无法有效地处理一些基本SQL查询,例如:

SELECT TOP (1) [t0].[Id], [t0].[L1], [t0].[L2], [t0].[Value]
FROM [Foos] AS [t0]
INNER JOIN [Lookup1] AS [t1] ON [t1].[Id] = [t0].[L2]
INNER JOIN [Lookup2] AS [t2] ON [t2].[Id] = [t0].[L1]
WHERE ([t1].[Name] = 'a') AND ([t2].[Name] = 'b')
ORDER BY [t0].[Value]
由LINQ表达式生成:

// query 1

Foos
.Where(f => f.Lookup1.Name == "a" && f.Lookup2.Name == "b")
.OrderBy(f => f.Value)
.Take(1)
// query 2

(from f in Foos
from l in (
    from l1 in Lookup1s
    from l2 in Lookup2s
    where l1.Name == "a"
        && l2.Name == "b"
    select new { L1 = l1.Id, L2 = l2.Id }).Take(1)
where f.L1 == l.L1 && f.L2 == l.L2
orderby f.Value descending
select f).Take(1)
架构定义有问题“”@答案中的提示显示SQL查询必须如下所示:

SELECT TOP (1) [t0].[Id], [t0].[L1], [t0].[L2], [t0].[Value]
FROM [Foos] AS [t0]
CROSS JOIN (
    SELECT TOP (1) [t1].[Id], [t2].[Id] AS [Id2]
    FROM [Lookup1] AS [t1], [Lookup2] AS [t2]
    WHERE ([t1].[Name] = 'a') AND ([t2].[Name] = 'b')
    ) AS [t3]
WHERE ([t0].[L1] = [t3].[Id]) AND ([t0].[L2] = [t3].[Id2])
ORDER BY [t0].[Value] DESC
可由以下LINQ表达式生成:

// query 1

Foos
.Where(f => f.Lookup1.Name == "a" && f.Lookup2.Name == "b")
.OrderBy(f => f.Value)
.Take(1)
// query 2

(from f in Foos
from l in (
    from l1 in Lookup1s
    from l2 in Lookup2s
    where l1.Name == "a"
        && l2.Name == "b"
    select new { L1 = l1.Id, L2 = l2.Id }).Take(1)
where f.L1 == l.L1 && f.L2 == l.L2
orderby f.Value descending
select f).Take(1)
我的问题是如何将查询1自动重写为查询2?因此,我可以通过多个步骤组合查询:

void Do()
{
    var x = ListFoos("a", "b").OrderBy(f => f.Value).Take(2);
    // ...
}

IQueryable<Foos> ListFoos(string l1, string l2)
{
    var foos = Foos.AsQueryable();
    if (l1 != null)
        foos = foos.Where(f => f.Lookup1.Name == l1);
    if (l2 != null)
        foos = foos.Where(f => f.Lookup2.Name == l2);
    return foos;
}
voiddo()
{
var x=ListFoos(“a”,“b”).OrderBy(f=>f.Value).Take(2);
// ...
}
IQueryable ListFoos(字符串l1、字符串l2)
{
var foos=foos.AsQueryable();
如果(l1!=null)
foos=foos.Where(f=>f.Lookup1.Name==l1);
如果(l2!=null)
foos=foos.Where(f=>f.Lookup2.Name==l2);
返回foos;
}
已经有人这么做了吗?有一个图书馆可以简化这项任务吗

澄清:

IQueryable
的结果表达式被转换为SQL Server无法有效计算的SQL语句。因此,我需要将表达式转换为一个表达式,该表达式将被转换为更好的SQL Server SQL语句


我想我不是第一个遇到这个问题的人。LINQ在这里的时间更长,SQL语句也非常基本,因此其他开发人员可能已经在用SQL Server解决这个问题。

我不是100%确定我知道你在问什么,但如果我是对的,你应该看看PredicateBuilder。它非常有用。链接此处:

它是LinqKit的一部分:

下面是一些关于如何使用它的信息:

它基本上可以让你做这样的事情:

var predicate = PredicateBuilder.True<Foo>();
            if (l1 != null)
                predicate = predicate.And(f => f.Lookup1.Name == l1);
            if (l2 != null)
                predicate = predicate.Or(f => f.Lookup2.Name == l2);

            return Foos.Where(predicate);
var predicate=PredicateBuilder.True();
如果(l1!=null)
谓词=谓词和(f=>f.Lookup1.Name==l1);
如果(l2!=null)
谓词=predicate.Or(f=>f.Lookup2.Name==l2);
返回Foos.Where(谓词);

注:以上内容来自内存。。我还没有测试过这个…所以可能有一些输入错误…

我需要在运行时进行测试。所以我可以重写在多个函数调用中形成的查询。(l1和l2是用户提供的变量。)没有自动的方法,但是当你说
SQL Server无法有效地处理一些基本的SQL查询时,我想知道你为什么会得出这个结论。请看。“我不是100%肯定我知道你在问什么。”。所以要求澄清。你的回答太离谱了。@GertArnold:谢谢你的评论,但是OP的话是“这样我就可以在多个步骤中组合查询”,最后的代码示例似乎表明我的结论是正确的。也许我错了。在我看来,OP正在寻找一种自动化的方法,将查询塑造成一种能够产生更好SQL的形式,这样他就可以先组合查询,然后再重新塑造查询。这主要是关于重塑。但如果你不确定的话,问问他。@GertArnold是对的。我有一个
IQueryable
,它生成SQL Server无法有效评估的SQL。因此,我正在寻找一个库,它可以帮助我翻译
IQueryable的
表达式,从而生成更好的SQL。