【问题标题】:Extract sql query from LINQ expressions从 LINQ 表达式中提取 sql 查询
【发布时间】:2010-01-08 05:25:30
【问题描述】:

是否可以从 LINQ 查询中提取 sql 语句?

说,我有这个 LINQ 表达式。

        string[] names =
            new string[] { "Jon Skeet", "Marc Gravell", "tvanfosson", 
                           "cletus", "Greg Hewgill", "JaredPar" };

        var results = from name in names
                      where name.StartsWith("J")
                      select name;

alt text http://ruchitsurati.net/files/linq-debugging.png

在此语句之后,“结果”仅包含 LINQ 表达式,而不是由于延迟执行 LINQ 查询而导致的结果。

我可以从“结果”中提取或生成 LINQ 查询吗? 准备一个有效的 SQL 语句 查询存储在“LINQ”中?

编辑

这是我的目标:

我们已经编写了自己的 ORM。每次需要进行数据库操作时,我们都必须编写查询。现在我们需要在 DAL 摆脱它。我们希望在代码中编写 LINQ 表达式,它将针对我的 ORM 生成 SQL 语句,我们将在数据库上执行此 SQL。

我是否会编写自定义 Linq 提供程序来满足我的需要?

【问题讨论】:

  • 您尝试做的事情是可以理解的,但是编写自己的 Linq Provider 是一项非常大的工作。我知道没有捷径可以让你更快地到达那里。
  • 您的 png 链接已失效。不错的宠物项目,但你的屏幕截图也在那里死了。

标签: c# linq linq-to-sql


【解决方案1】:

编辑:等等,你说的是 LINQ to Objects?不,那是不可能的1。无法将 LINQ to Object 查询的表达式树转换为表示查询某个数据库的表达式树。

编辑:不要写你自己的 ORM。这个问题有经过验证的解决方案。你试图再次解决这个问题是在浪费价值。如果您要使用自己的 ORM,将表达式转换为 SQL 语句,是的,您必须编写自己的提供程序。这是 MSDN 上的 walkthrough 这样做。

但是说真的,不要编写自己的 ORM。五年前,在 NHibernate 和 LINQ to SQL 出现并成熟之前,很好。但是不是现在。没办法。

此答案的其余部分假设您询问的是 LINQ to SQL。

我知道有两种方法。

第一:

DataContext.Log 属性设置为Console.Out(或您选择的另一个System.IO.TextWriter):

var db = new MyDataContext();
db.Log = Console.Out;

这将在执行 SQL 语句时将它们打印到控制台。有关此功能的更多信息,请参阅MSDN。在其他地方有 examplesTextWriters 可让您将输出发送到调试器输出窗口。

第二:

使用 Scott Guthrie 的 LINQ to SQL Debug Visualizer。这使您可以通过 Visual Studio 中的调试器查看 SQL 语句。此选项的优点是您可以在不执行查询的情况下查看 SQL 语句。您甚至可以执行查询并在可视化工具中查看结果。

1:也许不是不可能,但肯定非常困难。

【讨论】:

  • 创建您自己的自定义记录器:msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx
  • 感谢您的回答。对于 Web API (EF),上面的代码(用于记录 SQL 语句)转换为:public ApplicationDbContext() : base("DefaultConnection") { Database.Log = Console.WriteLine; } 它应该放在 DbContext 构造函数中。
【解决方案2】:

编辑#2:更新和澄清完全改变了问题。

听起来您正在重新发明轮子并试图完成 LINQ to SQL 和 LINQ to Entities 已经完成的任务。例如,提供程序检查表达式树并将某些函数映射到 SQL Server。您将承担 Microsoft 已经为我们提供并经过广泛测试的大型任务。

使用现有的 ORM 解决方案会更好,无论是 Microsoft 的还是 NHibernate 等。


编辑 #1: 找到了,我知道我之前看到了一些东西,但我没有发现它。

可以使用DataContext.GetCommand method获取生成的SQL:

var query = dc.Persons.Take(1);
string generatedSql = dc.GetCommand(query).CommandText;

此示例从 AdventureWorks 数据库返回以下 SQL:

选择顶部 (1) [t0].[BusinessEntityID], [t0].[PersonType],[t0].[NameStyle], [t0].[Title], [t0].[FirstName], [t0].[MiddleName], [t0].[LastName], [t0].[后缀], [t0].[EmailPromotion], [t0].[AdditionalContactInfo], [t0].[人口统计],[t0].[rowguid] AS [Rowguid], [t0].[ModifiedDate] FROM [人].[人] AS [t0]


另一个用于确定生成语句的选项将在 VS2010 中通过 IntelliTrace(以前称为历史调试器)提供。有关更多信息和屏幕截图,请参阅此博客文章:Debugging LINQ to SQL queries using the Historical Debugger

这仅在调试期间有用,并且不提供以编程方式访问它的方法。

【讨论】:

  • 好吧,我不是在重新发明轮子。 DAL 使用传统的 ADO.NET 数据集,这就是我们访问数据的方式。我们只想使用 LINQ 为我们的自定义对象生成 SQL 语句。我们想要这样做的原因是我们有自己的 ORM,我们在这个 ORM 上开发应用程序。
【解决方案3】:

供以后参考,我认为这位先生的方法最好http://damieng.com/blog/2008/07/30/linq-to-sql-log-to-debug-window-file-memory-or-multiple-writers

class DebugTextWriter : System.IO.TextWriter {
   public override void Write(char[] buffer, int index, int count) {
       System.Diagnostics.Debug.Write(new String(buffer, index, count));
   }

   public override void Write(string value) {
       System.Diagnostics.Debug.Write(value);
   }

   public override Encoding Encoding {
       get { return System.Text.Encoding.Default; }
   }
}

myDataContext.Log = new DebugTextWriter();

【讨论】:

    【解决方案4】:

    您可以在数据库上启动 SQL Server Profiler 来跟踪您的 linq 查询。

    【讨论】:

      【解决方案5】:

      我发现一个更简单的方法是使用命令行窗口,您不需要输入任何额外的代码。在这里,您可以将名为 query 的 linq 语句打印到查询窗口:

      ? ((System.Data.Objects.ObjectQuery) 查询).ToTraceString()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多