Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq对实体复杂性的影响_C#_Sql Server_Entity Framework_Linq_Linq To Entities - Fatal编程技术网

C# Linq对实体复杂性的影响

C# Linq对实体复杂性的影响,c#,sql-server,entity-framework,linq,linq-to-entities,C#,Sql Server,Entity Framework,Linq,Linq To Entities,我从Linq to entities开始,也许有人能给我们一些启示 我有两个表-Vizite父表和Angajivizite子表。我首先使用数据库,所以我使用Vizite.Id和Angajivizite.IdVizita创建了它们之间的关系 我需要从Vizite中获取行,如果DataStart或DataEnd字段为null,或者Angactivizite中的子记录计数为零,则另一个位字段必须为0。也就是说,如果Vizite没有从属记录,或者这些数据字段中的任何一个为空,则计算字段为0 到目前为止,

我从Linq to entities开始,也许有人能给我们一些启示

我有两个表-Vizite父表和Angajivizite子表。我首先使用数据库,所以我使用Vizite.Id和Angajivizite.IdVizita创建了它们之间的关系

我需要从Vizite中获取行,如果DataStart或DataEnd字段为null,或者Angactivizite中的子记录计数为零,则另一个位字段必须为0。也就是说,如果Vizite没有从属记录,或者这些数据字段中的任何一个为空,则计算字段为0

到目前为止,我使用的linq工作正常。我使用的语法如下:

 var list = ctx.Vizite
                .OrderBy(p => p.DataEnd != null && p.DataStart != null && p.AngajatiVizite.Count > 0)
                .ThenBy(p => p.Data)
                .Select(p => new
                {
                    p.Id,
                    p.Numar,
                    p.Data,
                    p.DataStart,
                    p.DataEnd,
                    Programat = p.DataEnd != null && p.DataStart != null && p.AngajatiVizite.Count > 0
                })
                .ToList();
Linq生成的sql命令非常复杂,我不明白为什么它会如此复杂,有什么区别

我从linq那里得到的是:

SELECT 
[Project6].[Numar] AS [Numar], 
[Project6].[Id] AS [Id], 
[Project6].[Data] AS [Data], 
[Project6].[DataStart] AS [DataStart], 
[Project6].[DataEnd] AS [DataEnd], 
[Project6].[C2] AS [C1]
FROM ( SELECT 
    [Project5].[C1] AS [C1], 
    [Project5].[Id] AS [Id], 
    [Project5].[Numar] AS [Numar], 
    [Project5].[Data] AS [Data], 
    [Project5].[DataStart] AS [DataStart], 
    [Project5].[DataEnd] AS [DataEnd], 
    CASE WHEN ([Project5].[C2] > 0) THEN cast(1 as bit) WHEN ( NOT ([Project5].[C3] > 0)) THEN cast(0 as bit) END AS [C2]
    FROM ( SELECT 
        [Project4].[C1] AS [C1], 
        [Project4].[Id] AS [Id], 
        [Project4].[Numar] AS [Numar], 
        [Project4].[Data] AS [Data], 
        [Project4].[DataStart] AS [DataStart], 
        [Project4].[DataEnd] AS [DataEnd], 
        [Project4].[C2] AS [C2], 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[AngajatiVizite] AS [Extent5]
            WHERE [Project4].[Id] = [Extent5].[IdVizita]) AS [C3]
        FROM ( SELECT 
            [Project3].[C1] AS [C1], 
            [Project3].[Id] AS [Id], 
            [Project3].[Numar] AS [Numar], 
            [Project3].[Data] AS [Data], 
            [Project3].[DataStart] AS [DataStart], 
            [Project3].[DataEnd] AS [DataEnd], 
            (SELECT 
                COUNT(1) AS [A1]
                FROM [dbo].[AngajatiVizite] AS [Extent4]
                WHERE [Project3].[Id] = [Extent4].[IdVizita]) AS [C2]
            FROM ( SELECT 
                CASE WHEN ([Project2].[C1] > 0) THEN cast(1 as bit) WHEN ( NOT ([Project2].[C2] > 0)) THEN cast(0 as bit) END AS [C1], 
                [Project2].[Id] AS [Id], 
                [Project2].[Numar] AS [Numar], 
                [Project2].[Data] AS [Data], 
                [Project2].[DataStart] AS [DataStart], 
                [Project2].[DataEnd] AS [DataEnd]
                FROM ( SELECT 
                    [Project1].[Id] AS [Id], 
                    [Project1].[Numar] AS [Numar], 
                    [Project1].[Data] AS [Data], 
                    [Project1].[DataStart] AS [DataStart], 
                    [Project1].[DataEnd] AS [DataEnd], 
                    [Project1].[C1] AS [C1], 
                    (SELECT 
                        COUNT(1) AS [A1]
                        FROM [dbo].[AngajatiVizite] AS [Extent3]
                        WHERE [Project1].[Id] = [Extent3].[IdVizita]) AS [C2]
                    FROM ( SELECT 
                        [Extent1].[Id] AS [Id], 
                        [Extent1].[Numar] AS [Numar], 
                        [Extent1].[Data] AS [Data], 
                        [Extent1].[DataStart] AS [DataStart], 
                        [Extent1].[DataEnd] AS [DataEnd], 
                        (SELECT 
                            COUNT(1) AS [A1]
                            FROM [dbo].[AngajatiVizite] AS [Extent2]
                            WHERE [Extent1].[Id] = [Extent2].[IdVizita]) AS [C1]
                        FROM [dbo].[Vizite] AS [Extent1]
                    )  AS [Project1]
                )  AS [Project2]
            )  AS [Project3]
        )  AS [Project4]
    )  AS [Project5]
)  AS [Project6]
当我真正需要的是:

Select
Vizite.Id
, Vizite.Numar
, Vizite.Data
, Vizite.DataStart
, Vizite.DataEnd
, Case
    When DataStart != Null And DataEnd != Null And (Select Count(Id) From AngajatiVizite Where Vizite.Id = AngajatiVizite.IdVizita) > 0 Then 1
    Else 0
End As Programat
From Vizite
Order By Programat, Data
有谁能向我解释一下,为什么生成的SQL如此复杂,甚至不可能通过简单地阅读SQL语法来理解它


谢谢

如果执行以下操作,SQL语句的复杂性会发生什么变化

var list = ctx.Vizite
    .Select(p => new
    {
        p.Id,
        p.Numar,
        p.Data,
        p.DataStart,
        p.DataEnd,
        Programat =
            p.DataEnd != null && p.DataStart != null && p.AngajatiVizite.Count > 0
    }
    .OrderBy(p => p.Programat)
    .ThenBy(p => p.Data)
    .ToList();
我希望不要重复p.DataEnd!=null&&p.DataStart!=null&&p.angajivizite.Count>0并移动OrderBy,然后在选择之后移动by,您将得到一个更简单的查询

编辑

为了进一步简化SQL,您可以选择在从数据库获取原始数据后执行一些工作:

var list = ctx.Vizite
    .Select(p => new
    {
        p.Id,
        p.Numar,
        p.Data,
        p.DataStart,
        p.DataEnd,
        AngajatiViziteCount = p.AngajatiVizite.Count
    }
    .AsEnumerable() // do the rest of the work using LINQ to objects
    .OrderBy(p => p.DataEnd != null && p.DataStart != null && p.AngajatiViziteCount > 0)
    .ThenBy(p => p.Data)
    .ToList();

实体框架不会构建漂亮的查询,这是事实;有时这很麻烦,因为很难将SQL日志记录追溯到LINQ语句

但是,如果查询计划优化器不知道如何处理它们,这将是一个问题。幸运的是,就SQLServer而言,EF团队在EF5之后的每个版本中都设法使Sql更好地优化。因此,一般来说,您不应该太担心它,只有在性能比合理预期的更差时才开始研究它

不过,有一些经验法则。其中之一是只计算一次计算值。这就是let关键字派上用场的地方:

var list = (from p in ctx.Vizite
            let Programat = p.DataEnd != null && p.DataStart != null
                         && p.AngajatiVizite.Count > 0
            order by Programat, p.Data
            select new
            {
                p.Id,
                p.Numar,
                p.Data,
                p.DataStart,
                p.DataEnd,
                Programat
            }).ToList();

这在LINQ查询语法中运行良好。在fluent方法语法中,您可以执行完全相同的操作,但这需要两个后续Select语句。

之所以如此复杂,是因为您在linq中使用逻辑来选择实体。如果您这样做,EF通常会生成一个SQL子查询,而不是CASE子句。@CodeNotFound:您能给我一个替代方案吗?我是初学者,正在努力解决这个问题。有更好的方法吗?除了调用一个存储过程(我现在实际上正在这么做)之外,感谢您的帮助:事实上,生成的sql不太复杂,但仍然太复杂,IMO。它在字段列表中有两个以上的选择。。。。我无法将其粘贴到这里,因为注释字段限制为500个字符:@GrigoreDolghin,我用另一个想法编辑了我的答案。如果您正在寻找一个可以粘贴到长SQL语句中的位置,我建议您编辑您的问题并在结尾添加任何新内容。非常感谢大家。你的回答对理解它的工作原理很有帮助。