18

I'm using Linq to SQL. I have a DataContext against which I am .SubmitChanges()'ing. There is an error inserting the identity field, and I'd like to see the query it's using to insert this identity field.

I don't see the query itself within the quickwatch; where can I find it from within the debugger?

tsilb
  • 7,977
  • 13
  • 71
  • 98

7 Answers7

26

Lots of people have been writing their own "DebugWriter" and attaching it like so:

// 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()

This will output everything that Linq-to-Sql is doing into Visual Studio's debug window.

Portman
  • 31,785
  • 25
  • 82
  • 101
12

Further to Portman's answer, if you're a console application it's as simple as:

myDataContext.Log = Console.Out;

Or you could use something like Linq2SQL Profiler which is a rather excellent tool and in fact the right tool for the job:

Linq to SQL Profiler - Real-time visual debugger for Linq to SQL

Community
  • 1
  • 1
Kev
  • 118,037
  • 53
  • 300
  • 385
7

There is actually a very simple answer to your question

Just paste this in your watch window

((System.Data.Objects.ObjectQuery)myLinqQueryVar).ToTraceString()
Taha Rehman Siddiqui
  • 2,441
  • 5
  • 32
  • 58
  • unfortunately that doesn't always work. For exaple il your query has a groupby... – bobzer Oct 18 '13 at 23:44
  • the answer depend a lot of your entity framework from the version 4.1 you have the dbcontext which implement context.Log so you can use the solution you see below, but before that if you context heritate from objectcontext you have to do with the solution above except that unfortunable it's not always usable – bobzer Nov 06 '13 at 20:53
  • the answer was according to the question originally asked – Taha Rehman Siddiqui Nov 09 '13 at 17:18
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();
Loureiro
  • 41
  • 1
3

Run SQL Profiler if you have it. It'll show all traffic to your database, including SQL command text.

geofftnz
  • 9,954
  • 2
  • 42
  • 50
  • SQL Profiler is handy for other reasons too though, eg: seeing the load your code is putting on the DB. – geofftnz Mar 12 '09 at 02:16
1

I agree that Linq to SQL Profiler is the right tool for this job. But if you don't want to spend the money or just need to do something simple, I like the DebugTextWriter approach.

After reading this question I went off looking for something more robust. It turns out Damien Guard also wrote a very nice article about building different writers to deal with different things like outputting to Memory, Debug, a File, Multiple Destinations, or even using simple Delegates.

I wound up using a couple of his ideas and writing an ActionTextWriter that can handle more than one delegate, and I thought I would share it here:

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);
            }
        }
    }
}

You can add as many actions as you like. This example writes to a log file and the Console in Visual Studio via Debug.Write:

// 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);

And of course if you want to make simpler ones to use off the cuff, you can always extend ActionTextWriter... write the generic approach and reuse, right?

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);
        }
    }
}
bopapa_1979
  • 8,949
  • 10
  • 51
  • 76
-1

Here is detailed description: http://debugmode.net/2011/06/26/logging-in-linq-to-sql/

Vildan
  • 1,934
  • 1
  • 16
  • 17