如何从LINQ DataContext.SubmitChanges()获取TSQL查询

18

我正在使用Linq to SQL。 我有一个DataContext,针对它我正在执行.SubmitChanges()。 在插入标识字段时出现错误,我想看到用于插入此标识字段的查询。

我在快速监视中没有看到查询本身; 我可以在调试器中的哪里找到它?


您还可以配置数据上下文将查询输出到文件中。 - eglasius
7个回答

26

很多人都在编写自己的“DebugWriter”,并像这样进行附加:

// Add this class somewhere in your project...
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; }
   }
}

// Then attach it to the Log property of your DataContext...
myDataContext.Log = new DebugTextWriter()

这将把 Linq-to-Sql 所有的操作输出到 Visual Studio 的调试窗口。


12

7

其实,你的问题有一个非常简单的答案。

只需将以下内容粘贴到您的观察窗口中即可:

((System.Data.Objects.ObjectQuery)myLinqQueryVar).ToTraceString()

不幸的是,这并不总是有效。例如,如果您的查询具有groupby... - bobzer
答案很大程度上取决于您的实体框架版本。从4.1版本开始,您有了实现context.Log的dbcontext,因此您可以使用下面看到的解决方案。但在此之前,如果您的上下文继承自objectcontext,则必须使用上述解决方案,除非不幸的是它并不总是可用。 - bobzer
答案是根据最初提出的问题而来的。 - Taha Rehman Siddiqui

3
FooDataContext dc = new FooDataContext();

StringBuilder sb = new StringBuilder();
dc.Log = new StringWriter(sb);

var result=from r in dc.Tables select d;

.....
string query=sb.ToString();

3

如果您有 SQL Profiler,请运行它。它会显示所有访问数据库的流量,包括 SQL 命令文本。


SQL Profiler还有其他方便之处,例如:可以看到你的代码对数据库的负载情况。 - geofftnz

1

我认为 Linq to SQL Profiler 是这项工作的正确工具。但是如果您不想花钱或只需要做一些简单的事情,我喜欢 DebugTextWriter 方法。

阅读了这个问题后,我开始寻找更强大的工具。原来 Damien Guard 也写了一篇非常好的文章,介绍如何构建不同的编写器来处理不同的事情,比如输出到内存、调试、文件、多个目标,甚至使用简单的委托。

我最终采用了他的一些想法,并编写了一个 ActionTextWriter,可以处理多个委托,我想在这里分享一下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Writers
{
    public class ActionTextWriter : TextWriter
    {
        protected readonly List<Action<string>> Actions = new List<Action<string>>();

        public ActionTextWriter(Action<string> action)
        {
            Actions.Add(action);
        }

        public ActionTextWriter(IEnumerable<Action<string>> actions)
        {
            Actions.AddRange(actions);
        }

        public ActionTextWriter(params Action<string>[] actions)
        {
            Actions.AddRange(actions);
        }

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

        public override void Write(char[] buffer, int index, int count)
        {
            Write(new string(buffer, index, count));
        }

        public override void Write(char value)
        {
            Write(value.ToString());
        }

        public override void Write(string value)
        {
            if (value == null)
            {
                return;
            }

            foreach (var action in Actions)
            {
                action.Invoke(value);
            }
        }
    }
}

您可以添加任意数量的操作。此示例通过Debug.Write将日志文件和Visual Studio中的控制台写入:

// Create data context
var fooDc = new FooDataContext();

// Create writer for log file.
var sw = new StreamWriter(@"C:\DataContext.log") {AutoFlush = true};

// Create write actions.
Action<string> writeToDebug = s => Debug.Write(s);
Action<string> writeToLog = s => sw.Write(s);

// Wire up log writers.
fooDc.Log = new ActionTextWriter(writeToDebug, writeToLog);

当然,如果你想要制作更简单的用于即兴使用的版本,你总是可以扩展ActionTextWriter...编写通用方法并重复使用,对吧?

using System.Diagnostics;
using System.IO;

namespace Writers
{
    public class TraceTextWriter : ActionTextWriter
    {
        public TraceTextWriter()
        {
            Actions.Add(s => Trace.Write(s));
        }
    }

    public class FileTextWriter : ActionTextWriter
    {
        public FileTextWriter(string path, bool append = false)
        {
            var sw = new StreamWriter(path, append) {AutoFlush = true};
            Actions.Add(sw.Write);
        }
    }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接