Sending the LINQ To SQL log to the debugger output window

I was playing with LINQ To SQL (again) this evening, and I thought: why can't I see the generated SQL statements in my debugger output window?

The DataContext.Log property is a great help to learn writing LINQ To SQL queries. All you need to do is assign a TextWriter to it, and you get to see al the SQL statements generated by the data context. But where do you send them to? Console.Out is an option, but you probably don't want that in a release build. Furthermore, it doesn't quite work for Windows services or ASP.NET applications. That's why I wrote DebuggerWriter, an implementation of TextWriter that writes to the debugger log.

All you need to do to use it is:

MyDataContext db = new MyDataContext(); 
 
db.Log = new DebuggerWriter();


Here's the code:

using System; 
using System.Diagnostics; 
using System.Globalization; 
using System.IO; 
using System.Text; 
 
namespace Vandermotten.Diagnostics { 
    /// <summary> 
    /// Implements a <see cref="TextWriter"/> for writing information to the debugger log. 
    /// </summary> 
    /// <seealso cref="Debugger.Log"/> 
    public class DebuggerWriter : TextWriter 
    { 
        private bool isOpen; 
        private static UnicodeEncoding encoding; 
        private readonly int level; 
        private readonly string category; 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class. 
        /// </summary> 
        public DebuggerWriter() 
            : this(0, Debugger.DefaultCategory) 
        { 
        } 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level and category. 
        /// </summary> 
        /// <param name="level">A description of the importance of the messages.</param> 
        /// <param name="category">The category of the messages.</param> 
        public DebuggerWriter(int level, string category) 
            : this(level, category, CultureInfo.CurrentCulture) 
        { 
        } 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level, category and format provider. 
        /// </summary> 
        /// <param name="level">A description of the importance of the messages.</param> 
        /// <param name="category">The category of the messages.</param> 
        /// <param name="formatProvider">An <see cref="IFormatProvider"/> object that controls formatting.</param> 
        public DebuggerWriter(int level, string category, IFormatProvider formatProvider) 
            : base(formatProvider) 
        { 
            this.level = level; 
            this.category = category; 
            this.isOpen = true; 
        } 
 
        protected override void Dispose(bool disposing) 
        { 
            isOpen = false; 
            base.Dispose(disposing); 
        } 
 
        public override void Write(char value) 
        { 
            if (!isOpen) 
            { 
                throw new ObjectDisposedException(null); 
            } 
            Debugger.Log(level, category, value.ToString()); 
        } 
 
        public override void Write(string value) 
        { 
            if (!isOpen) 
            { 
                throw new ObjectDisposedException(null); 
            } 
 
            if (value != null) 
            { 
                Debugger.Log(level, category, value); 
            } 
        } 
 
        public override void Write(char[] buffer, int index, int count) 
        { 
            if (!isOpen) 
            { 
                throw new ObjectDisposedException(null); 
            } 
 
            if (buffer == null || index < 0 || count < 0 || buffer.Length - index < count) 
            { 
                base.Write(buffer, index, count); // delegate throw exception to base class 
            } 
 
            Debugger.Log(level, category, new string(buffer, index, count)); 
        } 
 
        public override Encoding Encoding 
        { 
            get 
            { 
                if (encoding == null) 
                { 
                    encoding = new UnicodeEncoding(false, false); 
                } 
 
                return encoding; 
            } 
        } 
 
        public int Level 
        { 
            get { return level; } 
        } 
 
        public string Category 
        { 
            get { return category; } 
        } 
    } 
}


Enjoy!


Comments

June 5. 2007 07:38 AM

Thanks for the code.  I was looking for an easy solution to see the Sql when debugging with ASP.NET, and this works great!  Thanks, Paul Wilson http://weblogs.asp.net/PWilson

July 25. 2007 11:46 PM

Great code, very handy thing for the ol' toolbox.  Would there be a way to have the class return a string of the generated sql, instead of outputting to debug?

July 26. 2007 12:16 AM

If you want a string, just use System.IO.StringWriter instead of this class. The ToString() method on StringWriter returns the string you're looking for.

December 23. 2007 07:39 AM

What about things done within SubmitChanges?  How can we tap into the SQL generated there?

February 27. 2008 06:20 AM

Works really well and is exaclty what I was looking for, can I use it in a project for work?

February 27. 2008 10:04 AM

> can I use it in a project for work?  Sure. And I don't mind if you give me credit in the source Wink  Kris.

March 7. 2008 12:44 PM

This works great, thanks!

April 9. 2008 04:42 PM

Neat!  One suggestion I might make would be to do away with the backing fields (eg, "level" and "category") and just use the pattern:  public string Level { get; private set; } public string Category { get; private set; }  I find this helps clean up the API by reducing the number of places you access the data.  Useful if you're trying to rationalize side-effects, particularly with WPF.  Admittedly, you don't have the write-once that "readonly" gives you, but you can always suggest readonly autoproperties for the next version of C# ;)

April 30. 2008 09:20 AM

just works

May 16. 2008 02:58 AM

Very neat, thanks for sharing this.  Just so that the next en-passants who work in VB, spare the few minutes to convert from C#, here is the same class in VB.net   Cheers, J.  --  Imports System Imports System.Diagnostics Imports System.Globalization Imports System.IO Imports System.Text   '''

''' Implements a for writing information to the debugger log. ''' ''' Public Class DebuggerWriter  Inherits TextWriter   Private isOpen As Boolean  Private Shared s_Encoding As UnicodeEncoding  Private ReadOnly m_Level As Integer  Private ReadOnly m_Category As String   '''   ''' Initializes a new instance of the class.  '''   Public Sub New()   Me.new(0, Debugger.DefaultCategory)  End Sub   '''   ''' Initializes a new instance of the class with the specified level and category.  '''   ''' A description of the importance of the messages.  ''' The category of the messages.  Public Sub New(ByVal level As Integer, ByVal category As String)   Me.New(level, category, CultureInfo.CurrentCulture)  End Sub   '''   ''' Initializes a new instance of the class with the specified level, category and format provider.  '''   ''' A description of the importance of the messages.  ''' The category of the messages.  ''' An object that controls formatting.  Public Sub New(ByVal level As Integer, ByVal category As String, ByVal formatProvider As IFormatProvider)   MyBase.New(formatProvider)   Me.M_Level = level   Me.M_Category = category   Me.isOpen = True  End Sub   Protected Overrides Sub Dispose(ByVal disposing As Boolean)   isOpen = False   MyBase.Dispose(disposing)  End Sub   Public Overrides Sub Write(ByVal value As Char)   If Not isOpen Then    Throw New ObjectDisposedException(Nothing)   End If   Debugger.Log(M_Level, M_Category, value.ToString())  End Sub   Public Overrides Sub Write(ByVal value As String)   If Not isOpen Then    Throw New ObjectDisposedException(Nothing)   End If   If (value IsNot Nothing) Then    Debugger.Log(M_Level, M_Category, value)   End If  End Sub   Public Overrides Sub Write(ByVal buffer As Char(), ByVal index As Integer, ByVal count As Integer)   If Not isOpen Then    Throw New ObjectDisposedException(Nothing)   End If   If (buffer Is Null OrElse index < 0 OrElse count < 0 OrElse buffer.Length - index < count) Then    MyBase.Write(buffer, index, count) ' delegate throw exception to base class   End If   Debugger.Log(M_Level, M_Category, New String(buffer, index, count))  End Sub   Public Overrides ReadOnly Property Encoding() As Encoding   Get    If (s_Encoding Is Nothing) Then     s_Encoding = New UnicodeEncoding(False, False)    End If    Return s_Encoding   End Get  End Property   Public ReadOnly Property Level() As Integer   Get    Return m_Level   End Get  End Property   Public ReadOnly Property Category() As String   Get    Return m_Category   End Get  End Property  End Class  

May 16. 2008 03:15 AM

Thanks J.

May 16. 2008 11:11 AM

Very good for demos...

September 4. 2008 03:41 PM

My be dumb question... Could you do something similar right in the Trace object with an extension method? Otherwise real handy thanks.

September 8. 2008 01:55 AM

I'm not sure what you mean. Are you refering to the System.Diagnostics.Trace class? I'd say simply use a DefaultTraceListener (which is used by default anyway).  And BTW, extension methods don't work on that one, because you don't have any instace objects, just a static class.

October 8. 2008 05:25 PM

Super, i've been looking around for a way to send to the debugger in vs2008 for some time. Thanx!

October 13. 2008 05:37 AM

Thank you Kris, and also to J. for the VB version!

October 14. 2008 03:25 AM

Very useful.  Thanks.

October 19. 2008 06:27 PM

Nice code, thank you.

November 20. 2008 05:42 PM

very userful ! thank you

February 10. 2009 12:23 AM

This a very nice little tool, it makes debugging and optimizing linq queries much, much easier. Great stuff!

July 16. 2009 10:32 AM

Thanks for sharing this, very useful indeed.

July 21. 2009 03:06 AM

Helped a lot, ty.

July 31. 2009 07:13 AM

For anyone that isn't sure, this outputs to the Immediate Window in VS 2008.  Thanks for a really useful class, much appreciated.  Chris  http://www.keeblesolutions.com

September 5. 2009 04:35 AM

Thanks for the code!  Really nice work!  Marc Weber www.dev-web.nl

January 7. 2010 01:23 PM

Mobilt bredbånd

There are certainly a lot of details like that to take into consideration. That is a great point to bring up. I offer the thoughts above as general inspiration but clearly there are questions like the one you bring up where the most important thing will be working in honest good faith. I don?t know if best practices have emerged around things like that, but I am sure that your job is clearly identified as a fair game.

Mobilt bredbånd

January 7. 2010 02:11 PM

Bredbånd

Well, this is my first visit to your blog! We are a group of volunteers and starting a new initiative in a community in the same niche. Your blog provided us valuable information to work on. You have done a marvellous job!

Bredbånd

January 8. 2010 10:41 PM

free lawyers

Nice information, many thanks to the author. It is incomprehensible to me now, but in general, the usefulness and significance is overwhelming. Thanks again and good luck!

free lawyers

January 9. 2010 07:34 AM

15 lcd

Hello,I love reading through your blog, I wanted to leave a little comment to support you and wish you a good continuation. Wishing you the best of luck for all your blogging efforts.

15 lcd

January 12. 2010 12:36 AM

how to sell on amazon

Nice to be visiting your blog again, it has been months for me. Well this article that i've been waited for so long. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share.

how to sell on amazon

January 12. 2010 01:30 AM

safety training

Excellent read, I just passed this onto a colleague who was doing a little research on that. And he actually bought me lunch because I found it for him smile So let me rephrase that: Thanks for lunch!

safety training

January 15. 2010 03:16 AM

stock loan

Have you ever considered adding more videos to your blog posts to keep the readers more entertained? I mean I just read through the entire article of yours and it was quite good but since I'm more of a visual learner,I found that to be more helpful well let me know how it turns out! I love what you guys are always up too. Such clever work and reporting! Keep up the great works guys I've added you guys to my blogroll. This is a great article thanks for sharing this informative information.. I will visit your blog regularly for some latest post.

stock loan

January 15. 2010 09:05 AM

compare pet insurance

Took me time to read all the comments, but I really enjoyed the article. It proved to be Very helpful to me and I am sure to all the commenters here! It's always nice when you can not only be informed, but also entertained! I'm sure you had fun writing this article.

compare pet insurance

January 18. 2010 09:47 PM

Ventrilo Hosting

I have been surfing online more than three hours today, yet I never found any interesting article like yours. It's pretty worth enough for me. In my opinion, if all webmasters and bloggers made good content as you did, the internet will be much more useful than ever before.

Ventrilo Hosting

January 23. 2010 08:51 PM

magnetic crayola easel

When I originally commented I clicked the "Notify me when new comments are added" checkbox and now each time a comment is added I get four emails with the same comment.
Is there any way you can remove me from that service?
Thanks!

magnetic crayola easel

January 23. 2010 08:52 PM

pendant light fixtures

Excellent read, I just passed this onto a colleague who was doing a little research on that. And he actually bought me lunch because I found it for him smile So let me rephrase that: Thanks for lunch!

pendant light fixtures

January 24. 2010 10:02 PM

Tutor

That is some inspirational stuff. Never knew that opinions could be this varied. Thanks for all the enthusiasm to offer such helpful information here.

Tutor

January 27. 2010 04:30 AM

medical billing services

Excellent read, I just passed this onto a colleague who was doing a little research on that. And he actually bought me lunch because I found it for him smile So let me rephrase that: Thanks for lunch!

medical billing services

January 30. 2010 02:16 AM

cheap pay as you go mobile phones

That is some inspirational stuff. Never knew that opinions could be this varied. Thanks for all the enthusiasm to offer such helpful information here.

cheap pay as you go mobile phones

January 31. 2010 04:29 PM

Home Remodeling

This is such a great resource that you are providing and you give it away for free. I love seeing websites that understand the value of providing a quality resource for free. It is the old what goes around comes around routine. Did you acquired lots of links and I see lots of trackbacks??

Home Remodeling

February 4. 2010 03:28 PM

yogurt for acne

That is some inspirational stuff. Never knew that opinions could be this varied. Thanks for all the enthusiasm to offer such helpful information here.

yogurt for acne

February 4. 2010 05:56 PM

huggies couons

I thought it was going to be some boring old post, but it really compensated for my time. I will post a link to this page on my blog. I am sure my visitors will find that very useful.

huggies couons

February 5. 2010 01:31 PM

business websites

I have recently started using the blogengine.net and I having some problems here? in your blog you stated that we need to enable write permissions on the App_Data folder...unfortunately I don't understand how to enable it.

business websites

February 7. 2010 10:06 PM

swing trading

Great post! I am just starting out in community management/marketing media and trying to learn how to do it well - resources like this article are incredibly helpful. As our company is based in the US, it?s all a bit new to us. The example above is something that I worry about as well, how to show your own genuine enthusiasm and share the fact that your product is useful in that case.

swing trading

February 8. 2010 12:49 PM

post menopause

Took me time to read all the comments, but I really enjoyed the article. It proved to be Very helpful to me and I am sure to all the commenters here! It's always nice when you can not only be informed, but also entertained! I'm sure you had fun writing this article.

post menopause

February 9. 2010 04:30 AM

affordable health care insurance

This is a really good read for me, Must admit that you are one of the best bloggers I ever saw.Thanks for posting this informative article.

affordable health care insurance

February 13. 2010 06:57 PM

organic mattress

Keep 'em coming... you all do such a great job at such Concepts... can't tell you how much I, for one appreciate all you do!

organic mattress

February 13. 2010 09:26 PM

La Marque Garage Door Repair

I was looking for crucial information on this subject. The information was important as I am about to launch my own portal. Thanks for providing a missing link in my business.

La Marque Garage Door Repair

February 14. 2010 02:03 PM

best cell phone screen protector

Howdy, i read your blog occasionally and i own a similar one and i was just wondering if you get a lot of spam comments? If so how do you prevent it, any plugin or anything you can advise? I get so much lately it's driving me mad so any assistance is very much appreciated.

best cell phone screen protector

February 15. 2010 03:01 PM

best acne treatment

This is such a great resource that you are providing and you give it away for free. I love seeing websites that understand the value of providing a quality resource for free. It is the old what goes around comes around routine. Did you acquired lots of links and I see lots of trackbacks??

best acne treatment

February 16. 2010 01:51 PM

Papillon training

Hello,I love reading through your blog, I wanted to leave a little comment to support you and wish you a good continuation. Wishing you the best of luck for all your blogging efforts.

Papillon training

March 16. 2010 09:51 AM

emekli sandıgı

This is a really good read for me, Must admit that you are one of the best bloggers I ever saw.Thanks for posting this informative article.

emekli sandıgı

March 16. 2010 04:31 PM

arac sorgulama

I admire the valuable information you offer in your articles. I will bookmark your blog and have my children check up here often. I am quite sure they will learn lots of new stuff here than anybody else!

arac sorgulama

March 31. 2010 07:46 AM

ID Payday Loans

Remember you will not always win. Some days, the most resourceful individual will taste defeat. But there is, in this case, always tomorrow - after you have done your best to achieve success today.

ID Payday Loans

April 6. 2010 07:30 PM

hikaye

Thanks a lot for enjoying this beauty article with me. I am apreciating it very much! Looking forward to another great article. Good luck to the author! all the best!

hikaye

April 15. 2010 03:05 PM

kapadokya

Excellent post.I want to thank you for this informative read, I really appreciate sharing this great post. Keep up your work.

kapadokya

April 21. 2010 09:24 PM

plaka sorgulama

Thanks a lot for enjoying this beauty article with me. I am apreciating it very much! Looking forward to another great article. Good luck to the author! all the best!

plaka sorgulama

April 23. 2010 07:39 AM

rezzan kiraz

I just couldnt leave your website before saying that I really enjoyed the quality facts you provide to all your visitors. Would be back generally to check up on new stuff in you article!

rezzan kiraz

April 23. 2010 07:55 PM

fallar fal bakma

Thanks a lot for enjoying this beauty article with me. I am apreciating it very much! Looking forward to another great article. Good luck to the author! all the best!

fallar fal bakma

April 26. 2010 08:53 PM

trafik ceza sorgulama

Hello,I love reading through your blog, I wanted to leave a little comment to support you and wish you a good continuation. Wishing you the best of luck for all your blogging efforts.

trafik ceza sorgulama

April 28. 2010 08:47 AM

thy bilet fiyatları

Thank you for another great article. Where else could anyone get that kind of information in such a perfect way of writing? I have a presentation next week, and I am on the look for such information

thy bilet fiyatları

May 4. 2010 09:37 AM

bağkur borc sorgulama

This is a really good read for me, Must admit that you are one of the best bloggers I ever saw.Thanks for posting this informative article.

bağkur borc sorgulama

May 5. 2010 09:25 PM

sgk

I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post

sgk

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading