Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.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# EF重写规则是什么?_C#_Sql_Linq_Entity Framework_Code Generation - Fatal编程技术网

C# EF重写规则是什么?

C# EF重写规则是什么?,c#,sql,linq,entity-framework,code-generation,C#,Sql,Linq,Entity Framework,Code Generation,当使用DBContext编写LINQ查询语法表达式时,C#编译器会执行其通常的神奇操作。然后,在执行查询时,EF应用自己的内部重写规则来生成SQL表达式 就像我上面链接的文章一样,我希望有一个EF应用的重写规则列表。我在哪里能找到?如果我知道EF重写规则,我就可以预测EF将为给定查询生成什么样的SQL,而不必等到运行时才能“看到”生成的SQL 例如,考虑以下两个查询: var result = from c in context.Customers from a in

当使用DBContext编写LINQ查询语法表达式时,C#编译器会执行其通常的神奇操作。然后,在执行查询时,EF应用自己的内部重写规则来生成SQL表达式

就像我上面链接的文章一样,我希望有一个EF应用的重写规则列表。我在哪里能找到?如果我知道EF重写规则,我就可以预测EF将为给定查询生成什么样的SQL,而不必等到运行时才能“看到”生成的SQL

例如,考虑以下两个查询:

var result = from c in context.Customers
             from a in c.Accounts
             where c.ID > 2
             select a;

var result = from c in context.Customers
             where c.ID > 2
             from a in c.Accounts
             select a;
当C#编译器完成自己的重写规则时,上述查询将转换为具有以下各自格式的点表示法:

SelectMany(...).Where(...).Select(...); //for the first query

Where(...).SelectMany(...); // for the second query
在这些转换之后,EF开始应用自己的重写规则。但是对于上述两个查询,EF都有一个单一的规范化表单。换句话说,两个查询将产生相同的结果;任一查询都会生成以下SQL语句:

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Stat_ID] AS [Stat_ID]
    FROM  [dbo].[Customers] AS [Extent1]
    INNER JOIN [dbo].[Accounts] AS [Extent2] ON [Extent1].[ID] = [Extent2].[Customer_ID]
    WHERE [Extent2].[ID] > 2
如果不知道EF重写规则,我不可能预测到这一点。我只是需要执行和调试代码来进行观察

同样,我在哪里可以找到EF正在应用的重写规则列表


我也很好奇EF在应用规则方面有什么实施策略。下面是一篇讨论几个问题的文章。也许我可以通过研究EF源代码来发现这一点,但我正在做,但我还不在那里。

不幸的是,将linq表达式转换为SQL非常复杂,可能不太容易分解为一组简单的离散规则

例如,像linq
GroupBy
Join
这样的东西不会以相同的名称将一对一映射到SQL关键字,因为它们在linq中的行为与在SQL中的行为略有不同(linq
GroupBy
返回组中的所有项目,而不仅仅是聚合,linq
Join
更像SQL Server
交叉应用
)。实际的转换在很大程度上取决于在查询结束时选择的内容,这意味着您通常必须处理整个表达式,而不是简单地将linq方法映射到SQL关键字


非常值得阅读Matt Warrens关于构建linq提供程序的文章。这可能不是EF正在做的事情,但可以让您了解将linq表达式转换为sql所涉及的步骤以及所涉及的复杂性。

一切都取决于数据库连接器,例如,如果您想查看sql server的生成规则,y您可以查看。但我不建议您使用此规则,它们可能会在下一版本中更改。我使用MySql并更新了3次连接器,每次遇到EF生成不同查询和表达式的问题时,都会更新连接器。例如:

    .Where(p => new List<int> {1, 2}.Contains(p.value))
在6.7.4中,生成为:

   WHERE 1 = `value` OR 2 = `value`
   WHERE `value` IN (1, 2)

另外,如果您想查看MySql的生成规则,请检查源代码中的规则,因为它们非常复杂;我怀疑很难将它们列在易于阅读的列表中。在代码的一部分中,我看到了一堆描述某些规则的注释,它们位于SqlGenerator类中:。不过,我很确定在这个级别上有很多重写。我相信你误用了“重写规则”这个术语。你的意思是“sql生成规则”sql查询是由linq树生成的。重写另一方面是根据某些规则将给定类型的对象转换为相同类型的其他对象。您听说过LINQPad吗?这是一个允许您非常轻松地执行查询的工具-只需将它指向包含DbContext的DLL,可能还有连接字符串,您可以开始查询。它还允许您查看生成的SQL和IL,而无需编译和运行整个程序。它也是免费的:)我想您指的是。如“为实体框架编写提供程序时,必须将实体框架命令树转换为特定数据库可以理解的SQL,如Transact-SQL for SQL Server或PL/SQL for Oracle”中所述。您可以找到有关如何修改相应过程的一些详细信息。