C# LINQ或实体框架创建无界SQL语句

C# LINQ或实体框架创建无界SQL语句,c#,entity-framework,linq-to-entities,sql-optimization,C#,Entity Framework,Linq To Entities,Sql Optimization,我致力于应用程序的速度优化,我发现LINQ(或EF)正在为我创建一些奇怪的SQL,但运行速度很慢 下面是一些代码: SomeList.AddRange(_databaseView .Select(l=> new SomeViewModel { Date = l.Date,

我致力于应用程序的速度优化,我发现LINQ(或EF)正在为我创建一些奇怪的SQL,但运行速度很慢

下面是一些代码:

SomeList.AddRange(_databaseView
                .Select(l=> new SomeViewModel
                                {
                                    Date = l.Date,
                                    Details = l.Details,
                                    Level = l.LevelName,
                                    Id = l.ViewID,
                                    Message = l.Message,
                                    ProjectName = l.projectName,
                                    StatusId = l.StatusID,
                                    StatusName = l.StatusName
                                })
                .Skip(50)
                .Take(25));
理论上,它应该创建一个SQL语句,该语句需要25条记录,但profiler为它显示了以下SQL:

    SELECT [Extent1].[Date]  AS [Date],
       [Extent1].[ID]            AS [ID],
       [Extent1].[LevelID]       AS [LevelID],
       [Extent1].[StatusID]      AS [StatusID],
       [Extent1].[projectName]   AS [projectName],
       [Extent1].[LevelName]     AS [LevelName],
       [Extent1].[StatusName]    AS [StatusName],
       [Extent1].[Message]       AS [Message],
       [Extent1].[Details]       AS [Details],
       [Extent1].[LogViewID]     AS [LogViewID]
FROM   (SELECT [v_MyView].[Date]       AS [Date],
               [v_MyView].[ProjectID]     AS [ProjectID],
               [v_MyView].[LevelID]       AS [LevelID],
               [v_MyView].[StatusID]      AS [StatusID],
               [v_MyView].[projectName]   AS [projectName],
               [v_MyView].[LevelName]     AS [LevelName],
               [v_MyView].[StatusName]    AS [StatusName],
               [v_MyView].[Message]       AS [Message],
               [v_MyView].[Details]       AS [Details],
               [v_MyView].[ViewID]        AS [ID]
        FROM   [dbo].[v_MyView] AS [v_MyView]) AS [Extent1]
\u databaseView是一个IQueryable对象,我的所有排序和筛选逻辑都是在它上面完成的。

以下是我的一些想法: 如果我不做任何过滤,SQL是正常的,选择TOP(25)。但每当我做过滤的时候,有些事情就会搞砸。以下是我的一个过滤器的代码:

if (Filters.ProjectName != null && Filters.ProjectName[0] != 0)    // check if "all" is not checked
    _databaseView = Filters.ProjectName
        .Join(_databaseView,  f => f, l => l.ProjectID,  (f,l) => new SomeViewModel
                                                                           {
                                                                               Date = l.Date,
                                                                               Details = l.Details,
                                                                               LevelName = l.LevelName,
                                                                               ViewID = l.ViewID,
                                                                               Message = l.Message,
                                                                               projectName = l.projectName,
                                                                               StatusID = l.StatusID,
                                                                               StatusName = l.StatusName
                                                                           })
    .AsQueryable();
这是没有任何限制的。如何使LINQ-EF生成一些好的SQL


提前谢谢

实际更改正在使用的SQL的唯一方法是编写自己的SQL并使用它,而不是使用生成的SQL

您是指LINQ中未转换为SQL的Skip和Take部分。我认为这是因为你做LINQ的方式

试试像这样的东西

(From l In DataBaseView Select new SomeViewModel
                                {
                                    Date = l.Date,
                                    Details = l.Details,
                                    Level = l.LevelName,
                                    Id = l.ViewID,
                                    Message = l.Message,
                                    ProjectName = l.projectName,
                                    StatusId = l.StatusID,
                                    StatusName = l.StatusName
                                }).Skip(50).Take(25)
取而代之,看看它是否会对生成的代码产生影响


< >强> >编辑<强>,我错过了一部分,你说它应该是SQL,需要25个记录。

< P>如果你不能用适当的索引来获得SQL的足够好,那么你可以试着写一个存储过程并从LINQ调用它。< P> LINQ解析器,绝对要考虑<代码>跳过< /代码>。
在LINQ to Entities查询中采用
方法并生成正确的表达式树,然后对象服务将表达式树转换为命令树,该命令树将传递给数据库提供程序以生成特定的SQL查询。
在这种情况下,这两种方法影响生成的SQL,其中[Extent1].[row_number]>50和
分别为
Skip
Take
选择TOP(25)


现在,您确定在探查器中查看的跟踪是正确的吗?我建议在转到探查器之前先编写以下代码,然后通过代码调试并检查sql变量的值来查看该方法:

var query = _DatabaseView.Select(l=> new SomeViewModel {
                                                     Date = l.Date,
                                                     Details = l.Details,
                                                     Level = l.LevelName,
                                                     Id = l.ViewID,
                                                     Message = l.Message,
                                                     ProjectName = l.projectName,
                                                     StatusId = l.StatusID,
                                                     StatusName = l.StatusName})
                         .Skip(50)
                         .Take(25));
string sql = (query as ObjectQuery).ToTraceString();

尝试在选择之前移动跳过和执行。

您没有说明
\u DatabaseView
是什么,但根据您的结果,我猜测它不是
对象查询。这可以解释你的问题<代码>对象查询
将转换为SQL<代码>IEnumerable.Skip()不会。对可枚举项调用
AsQueryable()
,不足以实现这一点

例如,这:

var foo = MyObjectContext.SomeEntitySet.AsEnumerable().AsQueryable().Take(10);
…不会将
顶部
放在SQL中

但这是:

var bar = MyObjectContext.SomeEntitySet.Take(10);
。。。威尔


再一次:您还没有说什么是
\u DatabaseView
。直接在
ObjectContext
上尝试此操作,您将看到它是有效的。错误在您用来分配
\u DatabaseView
的代码中,您没有向我们展示。

我已经为此编写了一些存储过程,并且所有索引都已设置。。。因此,剩下的唯一问题是正确的跳过-执行逻辑。您可以非常轻松地将分页添加到存储过程中。在ROW_NUMBER()函数中使用一个通用的表表达式。这里没有必要,而且会损害可组合性。我更愿意保持分页。这样我可以让我的建筑更干净。我做到了。。。你甚至无法想象我放了多少地方=)最后有没有运气驯服EF?确切地说,
\u DatabaseView
是什么?是的,这里肯定是这样的。不_DatabaseView是一个IQueryable对象。我甚至在每次排序、筛选的最后都做了asqueryable()。。。。所以它是100%可读取的。也许我不够清楚<代码>AsQueryable()无法解决此问题。我将为您澄清答案。我在这里找到了一些类似的代码:这段代码在IEnumerable上完成所有操作。@Nazar,不,Troy Goode的
PagedList
类不是这样工作的。仔细阅读代码。我对这段代码非常熟悉,它并不是“在
IEnumerable
上做所有事情”