前陣子開發系統時,常在抓OracleCommand的執行期錯誤,有時是SQL語法寫錯,有時是參數數目不符,有時則是參數值給錯... (列原因寫到自己都汗顏,寫程式明明就要心思細膩,我的心思... 應該粗如電線桿吧?)

雖然VS2010在偵錯階段提供了很強的物件檢視功能,能逐一檢視物件的每個屬性且能逐層展開,必要時還可用即時運算視窗下指令做進一步操作分析,但每次要逐一檢查OracleCommand.Parameters還是有些麻煩,心想,如果能一次列出CommandText及所有參數的型別跟內容就太好了。

之前知道Visual Studio可以自訂Visualizer(視覺化檢視),在網路上撈了一下,只找得到現成的SqlCommand Visualizer,似乎沒人寫好OracleCommand用的檢視器,所以... 捲起袖子自己寫一個吧! 也順便體驗一下Visualizer的開發。

我必須要說,MSDN文件整理得真好,照著逐步解說教學一步步做,三兩下就可寫好一個Visualizer,而且連如何測試偵錯的環節都已考慮好,貼心得不得了。

我做了一個WinForm,放了RichTextBox(原本還想加上Highlighter為語法上色,不過後來因發懶作罷)及GridView分別顯示CommandText及列出OracleParameter,程式不難寫,唯一要克服的是OracleCommand不支援Serializable,無法直接使用內建的VisualizerObjectSource讀取執行期的物件,因此我自訂了一個OracleCommandVisualizerObjectSource,把必要資訊取出轉成XML傳回:

    public class OracleCommandVisualizerObjectSource : VisualizerObjectSource
    {
        public override void GetData(object target, Stream outgoingData)
        {
            XDocument xd = XDocument.Parse("<OracleCommand />");
            OracleCommand cmd = target as OracleCommand;
            xd.Root.Add(new XElement("CommandText", cmd == null ? 
                "null" : cmd.CommandText));
            xd.Root.Add(new XElement("Parameters"));
            XElement props = xd.Root.Element("Parameters");
            if (cmd != null)
                for (int i = 0; i < cmd.Parameters.Count; i++)
                {
                    OracleParameter p = cmd.Parameters[i];
                    props.Add(
                        new XElement(
                            "Parameter",
                            new XAttribute("No", i.ToString()),
                            new XAttribute("Name", p.ParameterName),
                            new XAttribute("DbType", p.DbType.ToString()),
                            new XAttribute("OracleType", p.OracleType.ToString()),
                            p.Value == null ? "null" : p.Value.ToString()
                            ));
                }
            base.GetData(xd.ToString(), outgoingData);
        }
    }

Visualizer在註冊時需特別宣告使用自訂VisualizerObjectSource:

using System.Data.OracleClient;
using System.Xml.Linq;
using Microsoft.VisualStudio.DebuggerVisualizers;
using OracleCommandVisualizer;
 
[assembly:System.Diagnostics.DebuggerVisualizer(
    typeof(DebuggerVisualizer), 
    typeof(OracleCommandVisualizerObjectSource), 
    Target = typeof(OracleCommand), 
    Description = "Afa OracleCommand Viewer")]
namespace OracleCommandVisualizer
{
    //REF: http://msdn.microsoft.com/en-us/library/ms164759.aspx
    public class DebuggerVisualizer : DialogDebuggerVisualizer
    {
        protected override void Show(
            IDialogVisualizerService windowService, 
            IVisualizerObjectProvider objectProvider)
        {
            VisualizerForm vf = new VisualizerForm(
                XDocument.Parse(objectProvider.GetObject().ToString()));
            vf.ShowDialog();
        }
 
        public static void TestShowVisualizer(object objectToVisualize)
        {
            VisualizerDevelopmentHost host = 
                new VisualizerDevelopmentHost(
                    objectToVisualize, typeof(DebuggerVisualizer),
                    typeof(OracleCommandVisualizerObjectSource));
            host.ShowVisualizer();
        }
    }
}

編譯完成後,將OracleCommandVisualizer.dll及OracleCommandVisualizer.pdb放到C:\Users\username\Documents\Visual Studio 2010\Visualizers,重新啟動VS2010,之後偵錯階段將滑鼠放到OracleCommand變數上,可按放大鏡圖示的向下箭頭叫出Visualizer:

如下圖所示,透過OracleCommand Viewer就可以一次看完CommandText跟所有OracleParameter內容,對於心思粗如電線桿的兩光程式工人來說,實在是一大恩物~~~

我已把專案放上CodePlex(http://oracmdvisualizer.codeplex.com/),有興趣下載玩玩或研究的同學可以過去看看。


Comments

# by Robin

多謝分享 ^_^

# by Ming

想問黑大..如果要改寫成SQL版本是否有需特別注意的地方呢!? 小弟不才....也想寫一個來使用!!

# by Jeffrey

to Ming, 改寫SQL版應該只要把Target = typeof(OracleCommand)換掉,另外做一個SqlCommandVisualizerObjectSource,在GetData()裡的處理對象換成SqlCommand/SqlParameter,顯示Form的部分可以共用(因為是吃XML,與Command型別無關),原則上改動幅度不大。另外,網路上可找到現成的SqlCommand Visualizer(http://www.codechimp.org/blog/post/SQL-Command-Visualizer-for-Visual-Studio-2005.aspx),你也可以參考看看。

# by Ming

感謝回覆,看來以我現在的程度要好好思考思考! 再不行我再求助公司大老! 若有成果,再行分享!!

# by Leo

感謝黑大~ 看完您的文章,我下午也用 VB.NET 做了一個 for VS2008 , Target Framework 2.0 的 Visualizer 來用 (工作環境需求)。大感謝~~ PS.MSDN真好用,看MSDN+黑大文章的說明,幾個小時就搞定了,感覺真好。 ^_^

Post a comment