IEのFormのデータを保存、復元する方法

JavaScriptでFormの値をJavaScriptとして保存し、
再度実行すれば、Formの値を復元するスクリプトです。
(Web Development Helperのスクリプトコンソールを利用します)

長大なFormのテストデータ入力時に役立つかもしれません。

 // 準備
 //     ・以下のページから「Web Development Helper」をダウンロードしてください。
 //       http://projects.nikhilk.net/Projects/WebDevHelper.aspx 
 //     ・ダウンロードしたファイルをインストールしてください。
 //     ・IEを起動し、「ファイル」メニューの「エクスプローラーバー」から「Web Development Helper」を
 //       選択してください。
 //     ・表示されたメニューの「HTTP Logging▼」を選択し、「Script Console」を選択してください。
 //     ・「Script Console」の右の「Enable Debugging」にチェックを付けてください。
 //        (「インターネットオプション」の「詳細」タブでスクリプトのデバッグを許可している必要があります。)
 //    
 // 使い方
 //     1:右ペインの「LoadScript」からこのスクリプトファイルを開き、「Execute」をクリックする。
 //     2:左ペインに表示された実行結果を全選択し、「Copy」をクリックする。
 //        (フォームのデータを復元するためのJavaScriptがコピーされます)
 //     3:再度同じ画面を開き、2でコピーしたスクリプトを実行すればフォームの値が復元されます。
 //        (select,checkbox,radio,hiddenの項目も復元されます)
 var scr = "";
 
 var selNm = "";
 var selType = "";
 var selIdx = 0;
 var aryIdx = "";
 
 var nameHash = new Array();
 
 dall = "window.document.all['";
 var end = ";\r\n";
 
 var forms;
 if( window.frames.length > 0 )
 {
     // フレームがある場合は最初のフレームからデータを取得する
     forms = window.frames[0].document.forms;
     dall = "window.frames[0].document.all['"
 }
 else
 {
     // フレームがない場合
     forms = window.document.forms;
 }
 
 for( i = 0; i < forms.length; i++ )
 {
     frm = forms[i];
     for( j = 0; j < frm.all.length; j++ )
     {
         tag = frm.all[j];
         if( tag.type != undefined )
         {
             // viewstateは保存しない
             if( tag.name == "__VIEWSTATE" )
             {
                 continue;
             }
             
             if( frm.all[tag.name] != undefined && 
                 frm.all[tag.name].length >= 2 && 
                 frm.all[tag.name][0].type == tag.type )    // selectのname属性が1つの場合と2つの場合で動作が異なるので回避
             {
                 if( nameHash[tag.name] == undefined )
                 {
                     nameHash[tag.name] = 0;
                 }
                 aryIdx = "[" + nameHash[tag.name] + "]";
                 nameHash[tag.name] += 1;
             }
             else
             {
                 aryIdx = "";
             }
             
             // text,textarea,hidden項目を保存
             if( tag.type == "text" ||  tag.type == "textarea" || tag.type == "hidden" )
             {
                 scr +=  dall + tag.name + "']" + aryIdx + ".value = '" + tag.value.replace(/\r\n/g, '\\r\\n') + "'" + end;
             }
             else if( tag.type == "checkbox" ||  tag.type == "radio" )
             {
                 scr +=  dall + tag.name + "']" + aryIdx + ".checked = " + tag.checked + end;
             }
             else if( tag.type == "select-one" || tag.type == "select-multiple" )
             {
                 selIdx = 0;
                 selNm = tag.name;
                 selType = tag.type;
             }
         }
         else
         {
             if( tag.tagName == "OPTION" )
             {
                 if( selType == "select-one" && tag.selected )
                 {
                     scr +=  dall + selNm + "']" + aryIdx + ".options[" + selIdx + "].selected = " + tag.selected + end;
                 }
                 else if( selType == "select-multiple")
                 {
                     scr +=  dall + selNm + "']" + aryIdx + ".options[" + selIdx + "].selected = " + tag.selected + end;
                 }
                 selIdx++;
             }
         }
     }
 }
 
 Debug.writeln(scr);

VSマクロ(プロパティー一括生成)をVS2003対応

2008/02/19 (火) VS2005マクロ(プロパティー一括生成)
のマクロをVisualStudio2003、VisualStudio2005両対応に修正。

Continue文がないだけで非常に読みづらい気がする・・・

If文をネストすればもっと単純になるけれど、ネスト深いプログラムは嫌いだし。


気になる点

VS2003でVBのソースからマクロを生成した場合

    Private _bar As Integer = 0
    ''' <summary>
    ''' 
    ''' </summary>
    Public Property Bar() As Int32
    〜以下略〜

Integer型が「Int32」として生成される。C#はちゃんと「int」になるのに。

VS2003のバグかも。

     ' 選択範囲の変数からプロパティーを生成する(VB.NET、C#対応)
     ' 既に同名のプロパティーがあれば作成しない
     ' 
     ' プロパティー名の規則
     ' 1:変数は"_"(アンダースコア)から始まること
     ' 2:プロパティー名は変数の先頭1文字を削除し、次の文字を大文字に変換した名前とする
     '   (ex. 「_foo 」→「Foo」)
     ' VS2003,VS2005対応
     Sub MakeProperty()
         ' 現在の選択範囲
         Dim sel As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
         Dim selTop As VirtualPoint = sel.TopPoint
         Dim selBottom As VirtualPoint = sel.BottomPoint
         ' もし下から上へ選択している場合は、選択範囲を交換する
         If selTop.Line = DTE.ActiveDocument.Selection.ActivePoint.Line Then
             sel.SwapAnchor()
         End If
 
         Dim actPoint As TextPoint = DTE.ActiveDocument.Selection.ActivePoint
         ' 現在キャレットがある場所のクラスを取得
         Dim elm As CodeElement = actPoint.CodeElement(vsCMElement.vsCMElementClass)
         Dim cls As CodeClass = elm
         Dim typ As CodeType = CType(elm, CodeType)
 
         'クラス内に既に存在するプロパティー一覧を作成する(重複作成しないためのチェック用)
         Dim lstProp As New System.Collections.Specialized.StringCollection
         For Each ite As CodeElement In typ.Members
             If TypeOf ite Is CodeProperty Then
                 lstProp.Add(ite.Name)
             End If
         Next
 
         ' 編集用オブジェクト
         Dim editPoint As EditPoint
         Dim sbProp As New System.Text.StringBuilder
 
         Dim blnContinue As Boolean = True
         Dim newLine As String = System.Environment.NewLine
         ' クラス内のメンバーに対して
         For Each ite As CodeElement In typ.Members
             blnContinue = True
             sbProp.Length = 0
 
             ' 変数であるかチェック
             If blnContinue AndAlso Not TypeOf ite Is CodeVariable Then
                 blnContinue = False
             End If
 
             ' 変数が選択範囲内かチェック
             Dim elmVal As CodeVariable = Nothing
             If blnContinue Then
                 elmVal = DirectCast(ite, CodeVariable)
                 Dim valLine As Integer = elmVal.StartPoint.Line
                 If Not (selTop.Line <= valLine AndAlso valLine <= selBottom.Line) Then
                     blnContinue = False
                 End If
             End If
 
             ' 変数名の先頭がアンダースコアであるかチェック
             If blnContinue AndAlso elmVal.Name.Substring(0, 1) <> "_" Then
                 blnContinue = False
             End If
 
             ' 同じ名前のプロパティーが存在している場合は作成しない
             If blnContinue AndAlso lstProp.Contains(GetPropNm(elmVal.Name)) Then
                 blnContinue = False
             End If
 
             ' プロパティー文字列を生成する
             If blnContinue Then
                 If DTE.ActiveDocument.Language = "Basic" Then
                     ' 編集中ファイルがVBの場合
                     sbProp.AppendFormat("''' <summary>").Append(newLine)
                     sbProp.AppendFormat("''' ").Append(newLine)
                     sbProp.AppendFormat("''' </summary>").Append(newLine)
                     sbProp.AppendFormat("Public Property {0}() As {1}", GetPropNm(elmVal.Name), elmVal.Type.AsString).Append(newLine)
                     sbProp.AppendFormat("    Get").Append(newLine)
                     sbProp.AppendFormat("        Return {0}", elmVal.Name).Append(newLine)
                     sbProp.AppendFormat("    End Get").Append(newLine)
                     sbProp.AppendFormat("    Set(ByVal value As {0})", elmVal.Type.AsString).Append(newLine)
                     sbProp.AppendFormat("        {0} = value", elmVal.Name).Append(newLine)
                     sbProp.AppendFormat("    End Set").Append(newLine)
                     sbProp.AppendFormat("End Property").Append(newLine)
                 ElseIf DTE.ActiveDocument.Language = "CSharp" Then
                     ' 編集中ファイルがC#の場合
                     sbProp.AppendFormat("/// <summary>").Append(newLine)
                     sbProp.AppendFormat("/// ").Append(newLine)
                     sbProp.AppendFormat("/// </summary>").Append(newLine)
                     sbProp.AppendFormat("public {0} {1}", elmVal.Type.AsString, GetPropNm(elmVal.Name)).Append(newLine)
                     sbProp.AppendFormat("{{").Append(newLine)
                     sbProp.AppendFormat("        get {{ return {0}; }}", elmVal.Name).Append(newLine)
                     sbProp.AppendFormat("        set {{ {0} = value; }}", elmVal.Name).Append(newLine)
                     sbProp.AppendFormat("}}").Append(newLine)
                 End If
 
                 ' 変数の次の行にプロパティーを追加する
                 editPoint = elmVal.EndPoint().CreateEditPoint()
                 editPoint.Insert(System.Environment.NewLine)
                 editPoint.Insert(sbProp.ToString)
             End If
 
         Next
         ' プロパティーのフォーマットを行う
         sel.LineDown(True, 12)
         sel.SmartFormat()
         sel.LineUp(False)
     End Sub
 
 
    ' 変数名からプロパティー名を生成して返す
     Private Function GetPropNm(ByVal varNm As String) As String
         Dim nm As String = varNm.Substring(1)
         Return nm.Substring(0, 1).ToUpper() & nm.Substring(1)
     End Function
 

VS2005マクロ(プロパティー一括生成)

VS2005マクロ(プロパティー一括生成)を書いてみた。

Eclipseを使っていたときお世話になった機能「GetterおよびSetterの生成」がVisualStudio2005になかったっぽいので作ってみました。

マクロがVC++6の頃とは随分変わってしまい困りましたがなんとかできました。

以下の行を選択してマクロを実行すると

    Private _foo As String = ""
    Private _bar As Integer = 0

以下のようにプロパティーが一括生成されます

    Private _foo As String = ""
    ''' <summary>
    ''' 
    ''' </summary>
    Public Property Foo() As String
        Get
            Return _foo
        End Get
        Set(ByVal value As String)
            _foo = value
        End Set
    End Property

    Private _bar As Integer = 0
    ''' <summary>
    ''' 
    ''' </summary>
    Public Property Bar() As Integer
        Get
            Return _bar
        End Get
        Set(ByVal value As Integer)
            _bar = value
        End Set
    End Property

参考にしたマクロ

  • VisualStudio2005のサンプルマクロ(「DevStudio6Editor」がVC++6のマクロを移植したものなので参考になります。)
  • VisualStudio2005のサンプルマクロ (Utilitiesの「InsertDocComments」)


C#とBasicに対応しています。(VisualStudio.NET2003は確認してません)

#Region "変数からプロパティーを生成"
     ' 選択範囲の変数からプロパティーを生成する(VB.NET、C#対応)
     ' 既に同名のプロパティーがあれば作成しない
     ' 
     ' プロパティー名の規則
     ' 1:変数は"_"(アンダースコア)から始まること
     ' 2:プロパティー名は変数の先頭1文字を削除し、次の文字を大文字に変換した名前とする
     '   (ex. 「_foo 」→「Foo」)
     Sub MakeProperty()
         ' 現在の選択範囲
         Dim sel As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
         Dim selTop As VirtualPoint = sel.TopPoint
         Dim selBottom As VirtualPoint = sel.BottomPoint
         ' もし下から上へ選択している場合は、選択範囲を交換する
         If selTop.Line = DTE.ActiveDocument.Selection.ActivePoint.Line Then
             sel.SwapAnchor()
         End If
 
         Dim actPoint As TextPoint = DTE.ActiveDocument.Selection.ActivePoint
         ' 現在キャレットがある場所のクラスを取得
         Dim elm As CodeElement = actPoint.CodeElement(vsCMElement.vsCMElementClass)
         Dim cls As CodeClass = elm
         Dim typ As CodeType = CType(elm, CodeType)
 
         'クラス内に既に存在するプロパティー一覧を作成する(重複作成しないためのチェック用)
         Dim lstProp As New System.Collections.Generic.List(Of String)
         For Each ite As CodeElement In typ.Members
             If TypeOf ite Is CodeProperty Then
                 lstProp.Add(ite.Name)
             End If
         Next
 
         ' 編集用オブジェクト
         Dim editPoint As EditPoint
         Dim sbProp As New Text.StringBuilder
 
         ' クラス内のメンバーに対して
         For Each ite As CodeElement In typ.Members
             sbProp.Length = 0
 
             ' 変数であるかチェック
             If Not TypeOf ite Is CodeVariable Then
                 Continue For
             End If
 
             ' 変数が選択範囲内かチェック
             Dim elmVal As CodeVariable = DirectCast(ite, CodeVariable)
             Dim valLine As Integer = elmVal.StartPoint.Line
             If Not (selTop.Line <= valLine AndAlso valLine <= selBottom.Line) Then
                 Continue For
             End If
 
             ' 変数名の先頭がアンダースコアであるかチェック
             If elmVal.Name.Substring(0, 1) <> "_" Then
                 Continue For
             End If
 
             ' 同じ名前のプロパティーが存在している場合は作成しない
             If lstProp.Contains(GetPropNm(elmVal.Name)) Then
                 Continue For
             End If
 
             ' プロパティー文字列を生成する
             If DTE.ActiveDocument.Language = "Basic" Then
                 ' 編集中ファイルがVBの場合
                 sbProp.AppendFormat("''' <summary>").AppendLine()
                 sbProp.AppendFormat("''' ").AppendLine()
                 sbProp.AppendFormat("''' </summary>").AppendLine()
                 sbProp.AppendFormat("Public Property {0}() As {1}", GetPropNm(elmVal.Name), elmVal.Type.AsString).AppendLine()
                 sbProp.AppendFormat("    Get").AppendLine()
                 sbProp.AppendFormat("        Return {0}", elmVal.Name).AppendLine()
                 sbProp.AppendFormat("    End Get").AppendLine()
                 sbProp.AppendFormat("    Set(ByVal value As {0})", elmVal.Type.AsString).AppendLine()
                 sbProp.AppendFormat("        {0} = value", elmVal.Name).AppendLine()
                 sbProp.AppendFormat("    End Set").AppendLine()
                 sbProp.AppendFormat("End Property").AppendLine()
             ElseIf DTE.ActiveDocument.Language = "CSharp" Then
                 ' 編集中ファイルがC#の場合
                 sbProp.AppendFormat("/// <summary>").AppendLine()
                 sbProp.AppendFormat("/// ").AppendLine()
                 sbProp.AppendFormat("/// </summary>").AppendLine()
                 sbProp.AppendFormat("public {0} {1}", elmVal.Type.AsString, GetPropNm(elmVal.Name)).AppendLine()
                 sbProp.AppendFormat("{{").AppendLine()
                 sbProp.AppendFormat("        get {{ return {0}; }}", elmVal.Name).AppendLine()
                 sbProp.AppendFormat("        set {{ {0} = value; }}", elmVal.Name).AppendLine()
                 sbProp.AppendFormat("}}").AppendLine()
             End If
 
             ' 変数の次の行にプロパティーを追加する
             editPoint = elmVal.GetEndPoint().CreateEditPoint()
             editPoint.Insert(System.Environment.NewLine)
             editPoint.Insert(sbProp.ToString)
         Next
         ' プロパティーのフォーマットを行う
         sel.LineDown(True, 12)
         sel.SmartFormat()
         sel.LineUp(False)
     End Sub
 
     ' 変数名からプロパティー名を生成して返す
     Private Function GetPropNm(ByVal varNm As String) As String
         Dim nm As String = varNm.Substring(1)
         Return nm.Substring(0, 1).ToUpper() & nm.Substring(1)
     End Function
 
 #End Region

英語の技術書が無料で読めるサイト

It Reading for freeで様々な技術系の本が公開されています。

全部で300種類のほどあるようです。All Books



個人的にいい加減Oracleとか勉強したかったので助かります。まだ途中までしか読んでないですが、とても読みやすい!

  • Oracle Esseitial
  • あとJava系も読んでおきたいです(仕事で使う事はなさそうですが)

  • Effective Java

  • THE Java™ Programming Language, Fourth Edition

  • 日本語版で読んでも理解できないかも・・・(読めるようになりたいなぁ)

  • Windows Internal
  • TableAdapter親クラスの変更

    TableAdapterクラスには親クラスを差し替える機能があるのは知っていたのですが、使い道は全く思いつきませんでした。
    (データセットデザイナで TableAdapterにあるBaseClassプロパティを変更することで親を変更できる)

    プログラミング MS ADO .NET2.0 (マイクロソフト公式解説書)

    プログラミング MS ADO .NET2.0 (マイクロソフト公式解説書)

    に書いてありましたが、著者も「どうやって使うかわからない」だそうです。


    でも有効利用しているサンプルを見つけました。
    http://www.codeproject.com/useritems/typed_dataset_transaction.asp


    TableAdapterでマニュアルトランザクションを使う簡単な方法はpartialクラスを使いTransactionを公開します。
    しかし、TableAdapterごとに書くのは面倒・・・

    ということで、親クラスでトランザクションの制御をするクラスを作ったようです。


    そのソース

    // ----------------------------------------------------------------------------
    //
    // TransactionSupport
    //
    // Original author: Mike Pagel
    //
    // After ideas given in
    //     http://www.codeproject.com/useritems/typed_dataset_transaction.asp
    //     http://entwickler-forum.de/showpost.php?p=2032&postcount=2
    //
    // ----------------------------------------------------------------------------
    
    using System.Data.SqlClient;
    using System.Data;
    using System.Reflection;
    
    namespace BizWiz
    {
        /// <summary>
        /// Transaction support for generated table adapters.
        /// </summary>
        /// <remarks>
        /// This class adds transaction support to table adapters. It is used by changing the base
        /// class of a table adapter from Component to this class. The implementation of this class
        /// then accesses the derived table adapter's properties through reflection.
        /// </remarks>
        public abstract class TransactionSupport : System.ComponentModel.Component
        {
            // --------------------------------------------------------------------
            #region Reflective access to table adapter properties
            // --------------------------------------------------------------------
            private SqlConnection Connection
            {
                // Access to propertis as public and non-public as generated table-adapter
                // scope seems to be different for different installations:
                // http://www.codeproject.com/useritems/transactionta.asp?msg=2225021#xx2225021xx
                get
                {
                    return (SqlConnection)GetType().GetProperty( "Connection", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( this, null );
                }
                set
                {
                    GetType().GetProperty( "Connection", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).SetValue( this, value, null );
                }
            }
    
            // --------------------------------------------------------------------
            private SqlDataAdapter Adapter
            {
                get
                {
                    return (SqlDataAdapter)GetType().GetProperty( "Adapter", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( this, null );
                }
            }
    
            // --------------------------------------------------------------------
            private SqlCommand[] CommandCollection
            {
                get
                {
                    return (SqlCommand[])GetType().GetProperty( "CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( this, null );
                }
            }
    
            #endregion
            // --------------------------------------------------------------------
            #region Properties
            // --------------------------------------------------------------------
            /// <summary>
            /// Transaction of this table adapter.
            /// </summary>
            /// <remarks>
            /// This property is used to share a transaction and its associated connection
            /// across multiple table adapters. The typical pattern is shown in the sample
            /// code below.
            /// </remarks>
            /// <example>
            /// XTableAdapter xta = new XTableAdapter();
            /// YTableAdapter yta = new YTableAdapter();
            /// 
            /// xta.BeginTransation();
            /// yta.Transation = xta.Transaction;
            /// try
            /// {
            ///     // perform xta and yta modifications here.
            ///     xta.CommitTransaction();
            /// }
            /// catch( Exception )
            /// {
            ///     xta.RollbackTransaction();
            /// }
            /// </example>
            public SqlTransaction Transaction
            {
                get
                {
                    return transaction;
                }
                set
                {                
                    // attach transaction to all commands of this adapter:
                    if( CommandCollection != null )
                    {
                        foreach( SqlCommand command in CommandCollection )
                        {
                            command.Transaction = value;
                        }
                    }
                    if( Adapter.InsertCommand != null )
                    {
                        Adapter.InsertCommand.Transaction = value;
                    }
                    if( Adapter.UpdateCommand != null )
                    {
                        Adapter.UpdateCommand.Transaction = value;
                    }
                    if( Adapter.DeleteCommand != null )
                    {
                        Adapter.DeleteCommand.Transaction = value;
                    }
             
                    // also set connection of this adapter accordingly:
                    if( value != null )
                    {
                        Connection = value.Connection;
                    }
                    else
                    {
                        // only clear connection if it was attached to
                        // transaction before:
                        if( transaction != null ) Connection = null;
                    }
    
                    transaction = value;
                }
            }
    
            #endregion
            // --------------------------------------------------------------------
            #region Operations
            // --------------------------------------------------------------------
            public void BeginTransaction()
            {
                // Open the connection, if needed
                if( Connection.State != ConnectionState.Open )
                    Connection.Open();
    
                // Create the transaction and assign it to the Transaction property
                Transaction = Connection.BeginTransaction();
            }
    
            // --------------------------------------------------------------------
            public void CommitTransaction()
            {
                // Commit the transaction
                Transaction.Commit();
    
                // Close the connection
                Connection.Close();
            }
    
            // --------------------------------------------------------------------
            public void RollbackTransaction()
            {
                // Rollback the transaction
                Transaction.Rollback();
    
                // Close the connection
                Connection.Close();
            }
    
            #endregion
            // --------------------------------------------------------------------
            #region Fields
            // --------------------------------------------------------------------
            /// <summary>
            /// Fields supporting properties.
            /// </summary>
            private SqlTransaction transaction;
    
            #endregion
            // --------------------------------------------------------------------
    
        }    
    }
    

    なるほど、リフレクションなら実行時にコネクション取れるわけですね。
    なるほど。


    使い方

    using (TransactionScope transaction = new TransactionScope())
    {
        adapter1.Update(table1);
        adapter2.Update(table2);
    
        transaction.Complete();
    }
    


    でも思ったのですがリフレクション使うんだったら、以下のようなstaticメソッド作って

    public static void SetTransaction(Component ta, SqlTransaction tx)
    {
        // コネクション取得
        Type typTA = ta.GetType();
        PropertyInfo propCon = typTA.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
    
        if (propCon == null)
        {
            throw new System.ArgumentException();
        }
    
        // テーブルアダプターの取得
        PropertyInfo propAdapter = typTA.GetProperty("Adapter", BindingFlags.NonPublic | BindingFlags.Instance);
        if (propAdapter == null)
        {
            throw new System.ArgumentException();
        }
    
        Object objAdapter = propAdapter.GetValue(ta, null);
        if (objAdapter is SqlDataAdapter)
        {
            // コネクションをテーブルアダプターにセットする
            propCon.SetValue(ta, tx.Connection, null);
            SqlDataAdapter adapter = (SqlDataAdapter)objAdapter;
    
            // 各コマンドにトランザクションをセットする
            SqlCommand[] CommandCollection = (SqlCommand[])typTA.GetProperty(
                "CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(ta, null);
    
            if (CommandCollection != null)
            {
                foreach (SqlCommand command in CommandCollection)
                {
                    command.Transaction = tx;
                }
            }
    
            if (adapter.UpdateCommand != null)
            {
                adapter.UpdateCommand.Transaction = tx;
            }
    
            if (adapter.InsertCommand != null)
            {
                adapter.InsertCommand.Transaction = tx;
            }
    
            if (adapter.DeleteCommand != null)
            {
                adapter.DeleteCommand.Transaction = tx;
            }
    
            if (adapter.SelectCommand != null)
            {
                adapter.SelectCommand.Transaction = tx;
            }
    
        }
    }
    

    こんな感じで使う方が簡単じゃないかと。
    (結局TableAdapterの親クラスをいちいち変更するのが面倒だと思う)

    using (SqlConnection con = new SqlConnection("〜〜〜"))
    {
        con.Open();
        SqlTransaction tx = con.BeginTransaction();
        DBUtil.SetTransaction(ta1, tx);
        DBUtil.SetTransaction(ta2, tx);
    
        ta1.Update();
        ta2.Update();
    
        tx.Commit();
    }
    

    VS2005買ったw

    会社の仕事(.NET2.0)が楽しかったからここ1年ほど家でプログラム書いてなかったけど、
    そろそろ飽きてきた。

    暇つぶし(否、現実逃避)には最高のソフトだと思う。


    というか、仕事中に調べるには気がひける・・・のを家でやるってのもどうかと思うが。

    もう少し汎用的に使えるビルドスクリプト

    SubVersionから最新ソースを取得してリビルドするサンプルスクリプト
    PropertyGroupは適宜変更してください

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="BuildAll"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <!-- カスタムタスクライブラリ MSBuildCommunityTasksを利用するための設定 -->
      <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    
      <PropertyGroup>
        <!-- ビルドプロジェクト名 -->
    	<ProjectName>BuildProj</ProjectName>
        <!-- SubVersionリポジトリ -->
    	<RepositoryPath>svn://localhost/BuildTest/trunk</RepositoryPath>
        <!-- SubVersionユーザ -->
    	<RepositoryUser>harry</RepositoryUser>
        <!-- SubVersionパスワード -->
    	<RepositoryPassword>harryssecret</RepositoryPassword>
        <!-- ビルド用ワークディレクトリ -->
    	<WorkingDirectory>.\Build</WorkingDirectory>
        <!-- コンフィグ -->
    	<BuildConfig>Release</BuildConfig>
        <!-- SMTPサーバ -->
    	<SMTPServer>SMTPServer</SMTPServer>
        <!-- エラーメール送信先 -->
    	<ErrorMailAddress>to_address@hogehoge.com</ErrorMailAddress>
      </PropertyGroup>
      
      <!-- ワークディレクトリを削除する -->
      <Target Name="CleanSource">
        <Message Text="Removing all source files from $(WorkingDirectory)" />
        <RemoveDir Directories="$(WorkingDirectory)" />
      </Target>
      
      <!-- Svnから最新のソースコードを取得する -->
      <Target Name="GetLatestFiles">
    	<Message Text="Checking out trunk into $(WorkingDirectory)" />
    	<SvnExport 
            RepositoryPath="$(RepositoryPath)" 
            LocalPath="$(WorkingDirectory)"
            UserName="$(RepositoryUser)"
            Password="$(RepositoryPassword)"> 
                <Output TaskParameter="Revision" PropertyName="Revision" />
        </SvnExport>
        <Message Text="Have got revision: $(Revision)"/>
      </Target>
    
      <!-- 取得したソースコードをコンパイルする -->
      <Target Name="Build">
    	<MSBuild Projects="$(WorkingDirectory)\$(ProjectName)\$(ProjectName).csproj" 
    	         Targets="ReBuild"  Properties="Configuration=$(BuildConfig);" />
        <!-- ビルド失敗時に実行するタスク -->
    	<OnError ExecuteTargets="ErrorMail" />
      </Target>
      
      
      <!-- ビルド失敗時メールを送信する -->
      <Target Name="ErrorMail" >
          <Mail SmtpServer="$(SMTPServer)" From="noreply@example.com" To="$(ErrorMailAddress)" 
              Subject="自動ビルド失敗  $(ProjectName)プロジェクト" Body="$(ProjectName)プロジェクトビルドに失敗しました。" />
      </Target>
      
      <!-- ビルドプロセスを実行する -->
      <Target Name="BuildAll">
        <CallTarget Targets="CleanSource" />
        <CallTarget Targets="GetLatestFiles" />
        <CallTarget Targets="Build" />
      </Target>
    </Project>