既存資産の.NET対応&移行方法 ~ Technical Seminar for Developer ~ マクロソフト株式会社 テクニカルソリューション推進統括本部 SE部 プリンシパル SE ジニゕス平井 Masato Genius Hirai はじめに ~ ウォーミング・ゕップ ~ .NETの仕組み ~ 実行エンジンと強力なラブラリ群 ~ .NETゕプリケーションを駆動させるランタムエンジン 多くの開発言語をサポート セキュリテゖシステムを搭載 堅牢な実行環境の提供 実行時コンパル バージョン管理機能 オブジェクト指向 MS VB MS C# MS J# 富士通 COBOL Sun Java VB コンパラ C# コンパラ J# コンパラ Cobol コンパラ Java コンパラ 中間言語 (MSIL) バトコード 共通言語ランラム (CLR) JavaVM OS/ハードウェゕ .NETゕプリを動作させるメカニズム ~ 実行時コンパルと厳格なセキュリテゖチェックがミソ ~ ソースコード コンパラ コンパラ ゕセンブリ EXE/DLL コンパラ (IL+MetaData) 署名検証審査 共通言語ランタム コンパル済み ゕセンブリ クラスローダー ジャストンタム コンパラ 実行 コードゕクセス セキュリテゖ審査 ネテゖブコード 中間コード ~ Microsoft Intermediate Language (MSIL) ~ ハードウェゕ(CPU)に依存しない命令セット //C# Source Code int x = 11; int y = 22; int z; z = x + y Source コンパル C#→MSIL // Code size 11 (0xb) .maxstack 2 .locals init ([0] int32 x, [1] int32 y, [2] int32 z) IL_0000: ldc.i4.s 11 IL_0002: stloc.0 IL_0003: ldc.i4.s 22 IL_0005: stloc.1 IL_0006: ldloc.0 IL_0007: ldloc.1 IL_0008: add.ovf MSIL IL_0009: stloc.2 'VB Dim Dim Dim z = Source Code x As Integer = 11 y As Integer = 22 z As Integer Source x + y コンパル VB→MSIL コンパル MSIL→native 00000000 00000001 00000003 00000006 00000007 00000008 00000009 0000000c 0000000f 00000011 00000013 00000015 0000001a 0000001f 00000021 00000023 00000025 00000027 push mov sub push push push mov mov xor xor xor mov mov mov add jno xor call ebp ebp,esp esp,14h edi esi ebx dword ptr [ebp-4],ecx dword ptr [ebp-8],edx esi,esi edi,edi ebx,ebx esi,0Bh edi,16h eax,esi eax,edi 0000002C ecx,ecx Native 75FB8597 ガベージコレクション ~ Noメモリリーク、Noリソースリーク ~ ガベージ コレクション マネージヒープの不要メモリをコンパクションする機構 世代(ジェネレーション)管理でパフォーマンスを向上 G0, G1, G2 の3世代 G0コンパクション → G1コンパクション → G2コンパクション 「新しいオブジェクト(G0)はすぐに消滅し、古いオブジェクト(G2 )は今後も利用させる可能性が高い」という統計のもとに実行 チューニングのためにパフォーマンス カウンタを提供 NextPtr 0 0 0 0 0 Object E Object D Object C Object B Object A 0 0 0 0 0 NextPtr Object F Object E Object D Object C Object B Object A GC 0 1 1 1 Object F Object E Object D Object B GC NextPtr 0 Object D 1 2 2 Object F Object E Object B .NET バージョンマトリクス ~ VS2003 と 1.1 ベースはそろそろ注意 ~ 1.0 ランタム バージョン トピック 対象 OS VS 2002 1.0.3705 ADO.NET ASP.NET WinForm 98 / Me / NT 2000, XP 1.1 1.1.4322 2.0 3.0 2.0.50727 832 SP1でバージョンゕップ → 3.5 2.0.50727 1433 ASP.NET 1.1 ADO.NET 2.0 ASP.NET 2.0 C# 2.0 VB 8.0 WPF WF WCF CardSpace ASP.NET AJAX LINQ C# 3.0 VB 9.0 98 / Me / NT 2000 XP / 2003 Vista 2000 sp3 XP sp2 2003 Vista 2008 XP sp2 2003 sp1 Vista 2008 XP sp2 2003 sp1 Vista 2008 ◎ VS 2003 ◎ VS 2005 ◎ △ VS 2008 ○ ○ ◎ 2011/01/12 2012/04/10 2013/04/09 サポート期限 2007/07/10 2008/10/14 Vista 上での開発ツールのサポート ~ VB6 だけがある意味、特別です ~ 実行環境 VB6ランタム .NET Framework 1.0 .NET Framework 1.1 .NET Framework 2.0 .NET Framework 3.0 .NET Framework 3.5 Yes No Yes Yes Yes Yes ← ← ← ← ← Visual Studio .NET 2002 Visual Studio .NET 2003 Visual Studio 2005 Windows Vista に標準搭載 Visual Studio 2008 開発環境 Visual Basic 6 Visual Studio 6 Visual C++ 6.0 Visual Studio .NET 2002 Visual Studio .NET 2003 Visual Studio 2005 Visual Studio 2005 + SP1 VS2005SP1+Update Patch Visual Studio 2008 Yes No No No No ← 作成したゕプリはOK No ← 作成したゕプリはOK No ← 作成したゕプリはOK Yes Yes Vista での VB 6.0 のサポート ~ 延長されましたが早めに.NETに移行しましょう ~ Visual Basic 6.0 開発環境(IDE)& 実行環境 サポートは 2008年4月8日 まで Visual Basic 6.0 はいまだ重要な位置づけを持っており、さらに 移行が比較的困難であるためサポートすることを決定 Windows Vista に Visual Basic 6.0 のランタムを同梱 サードパーテゖ製コンポーネント (ActiveXなど) サポートは提供できません。製造元に問い合わせて下さい ポント マクロソフトが VB6 およびランタムについてWindows Vista 上で動作することを検証するというレベル 修正パッチやSPが提供される可能性は非常に低い お客様のゕプリケーションが変更なしに Windows Vistaで動作す ることを保証するものではありません 参照 http://www.microsoft.com/japan/msdn/vbasic/support/vistasupport.aspx .NETを採用する必要性 ① ~ .NETに対応することで何が変わるのか? ~ 非常に堅牢な実行環境 障害を隔離する機能を搭載 メモリリーク、ゕクセスバオレーションを防止 「落ちない・減らない・固まらない」を実現 完璧なセキュリテゖ .NETのランタムがセキュリテゖを厳密に審査 ンターネット環境も意識したセキュリテゖ機構 驚異的なパフォーマンス Windows / Web もかつ大規模分散ゕプリケーションも向上 再ビルドすることなく 64ビットに対応 徹底したバージョンニング DLL 地獄に陥ることはない 一度動けば半永久的に動作する .NETを採用する必要性 ② ~ .NETに対応することで何が変わるのか? ~ 究極の開発生産性 開発言語の違いによる不可能がなくなり、難易度も同じ コンシューマからエンタープラズまでのすべてに一貫した プログラミング モデルを提供 多種多様のデバスに対応 配置・配布・保守コストの大幅削減 レジストリを使わないため配置やバックゕップがシンプル 仕様変更、機能追加に対しての俊敏性がある これまでの資産を有効活用 COMやDLLラブラリなど現行資産もフルに活躍 Webサービスなら非 Windowsシステムとの接続も容易 最新テクノロジーの積極的な採用 XML、SOAP、UDDI、WS-*、AJAX、XHTML などを実装 .NET Framework 3.0 ~ .NET は第3世代を迎えた ~ Microsoft .NET Framework 3.0 Windows Presentation Foundation Windows Foundation Windows Workflow Foundation Windows CardSpace™ UXの強化 分散ゕプリ構築 多様な形態 IDメタシステム 生産性向上 相互運用の実現 生産性と柔軟性 セキュゕで便利 形態の汎用性 サービス指向 拡張性 標準プロトコル Communication 相互運用の実現 .NET Framework 2.0 .NET Developer Stack ~ 最新・最強のラブラリ ~ ASP.NET AJAX ASP.NET 3.5 ASP.NET 2.0 LINQ Windows Forms 2.0 ADO.NET 2.0 WPF 3.5 WCF 3.5 WF 3.5 WPF 3.0 WCF 3.0 WF 3.0 Card Space 3.5 Card Space 3.0 Base Class Library 2.0 / 3.5 Common Language Runtime 2.0 CLR Windows Vista, Windows XP, Windows Server 2003 / 2008 .NET はすべてをカバー ~ 統合開発ツール Visual Studio とともに発展 ~ Windows ゕプリケーション Web ゕプリケーション WPF ゕプリケーション Workflow ゕプリケーション スマートデバス ゕプリケーション WCF サービス Windows サービス Sliverlight ゕプリケーション Office ゕプリケーション .NET ラブラリ 開発言語の選定 ~ .NETになってもVBで大丈夫か? ~ .NETでは多数のプログラミング言語が利用できます。また、各言語か ら.NET Frameworkの機能やクラスラブラリに平等にゕクセスできます。 このためプログラミング言語の違いによる機能差やパフォーマンスの差 はほとんど生じません。また、「C++のクラスをC#で継承してVBで使う」 といったような多言語とのシームレスな連携をサポートしています。 ほとんどの開発者は自分がもっとも得意とする「第1言語」を持ってい ます。そのスキルやこれまでの資産を最大限に活用して高い生産性を維持 することが可能です。 VBは世界最大のユーザー数を誇る開発言語です。今後もご安心して利用 できます。 開発言語の選択 ~ C#とVB.NETのどちらを選ぶか?それとも ~ Visual Basic VBA ASP 移行 Visual Basic 乗換 Amateur 新規 乗換 Visual J++ Java ASP 乗換 移行 Visual C++ C/C++ 継続 Visual C# Visual C++ (マネージC++) Visual C++ (Win32) Visual Basic ~ 圧倒的なユーザー数! もうVBに不可能はない ~ オブジェクト指向プログラミングを完全サポート 継承 / ポリモーフゖズム / オーバーロード 構造化例外処理 大量のOn Error 文から開放され保守性が向上 Try…Catch… Finally… フリースレッデゖング 安全なマルチスレッド・ゕプリケーションの作成が容易 .NET クラスラブラリにフルゕクセス 新しいプロジェクトタプ Windows サービス コンソール ゕプリケーション : サービス ゕプリケーション : コンソール ゕプリケーション ゕップグレード・ウゖザード VB6のコードを.NET用にコンバート ソースレベルでの変換率は約90%。無修正での稼動率が約40% Visual C# ~ 徹底したオブジェクト指向 .NET時代の開発言語 ~ ベースはC++ C++は難しい / 不要な機能が多すぎる / 開発者の手腕に依存 ANSI準拠のC++はそのまま .NET Framework Class Library の多くは C# で記述されている オブジェクト指向プログラミング言語 Javaプログラマも容易に使用 (Javaよりも多少複雑) 今後、主流になる開発言語 特徴 タプセーフ/オーバーフローチェック/配列の範囲チェック ポンタレス ただし、unsafeモードでの利用は可能 #include, マクロなど C++のコンストラクタを排除 ECMA スタンダード .NETスタンダードな言語として位置付け VB か C# か? ~ 機能的およびパフォーマンスの差はない ~ .NETでは何が最適な開発言語か? 好きな言語を使って下さい パフォーマンスはほとんど変わらない どの言語からも .NETの機能がすべて利用できる VB開発者がC#を取得できるのか? C や Javaの経験がなければかなり難しい VB6 から .NETへの移行は多少なりともエンジニゕの再教育が必要 どうせやるならオブジェクト指向が徹底されているC#がいい? オブジェクト指向の開発は、今後ますます重要になる VBより C のほうが優れているという悪しきメージ C# が.NETスタンダード言語であることは事実 どうせやるならオブジェクト指向が徹底されているC#がい 「VB6 開発者は VB.NETへ移行すること」が もっとも低コストで低リクスである .NETが提供する相互運用サービス ~ Win32と.NETマネージドコードの相互運用 ~ .NET Frameworkでは、マネージドコードからWindows APIや COM, ActiveXコントロールを利用するための相互運用サービスが 提供されています。すべてのコードを.NET Frameworkに移行する ことが最善の策ではありますが、大規模なプロジェクトやシステム では一度にすべてを.NETに移行させることは困難です。このた め、.NETとWin32(COM, Win32 API,..)のハブリッド的なソ リューションも有効な手段であり、既存の資産を有効に活用しつつ 段階的に.NET移行していくことが容易なのです。 プラットフォーム呼び出し ~ PInvoke : Platform Invocation Services ~ Win32 APIや C DLLの関数を呼び出す機構 マーシャリング機能(Managed Heap ←→Unmanaged Heap) エントリポント指定 System.Runtime.InteropServicesクラス Unmanaged DLL Windows API .NET Managed Code [DllImport("shell32.dll", EntryPoint="SHGetSpecialFolderPathW")] public static extern bool SHGetSpecialFolderPath( int Owner, [MarshalAs(UnmanagedType.LPWStr)] string Path, int Folder, int Created ); Private Declare Ansi Function SHGetSpecialFolderPath Lib "shell32.dll" Alias "SHGetSpecialFolderPathA" ( ByVal Owner As Integer, _ ByVal Path As String, _ ByVal Folder As Integer, _ ByVal Create As Integer _ ) As Boolean COM相互運用機能 ~ RCW : Runtime Callable Wrapper ~ .NETマネージコードからCOMを呼び出す機構 <InterOp>.DLL .NET→COM のプロキシの役割を担う”ラッパーDLL" COMを参照設定することで自動生成 タプ ラブラリ ンポータ (tlbimp.exe)で手動生成も可能 マーシャリング、参照カウント、ラフタムを管理 SuperCalc.Calculator obj = new SuperCalc.Calculator(); //C# Dim obj As New SuperCalc.Calculator() 'VB .NET Managed Code (クラゕント) Runtime Callable Wrapper IUnknown IFoo COM COM+ COM相互運用機能 ~ CCW : COM Callable Wrapper ~ COM(Win32ゕプリ)から .NET を呼び出す機構 .NETのクラスラブラリ(DLL)をCOM/COM+のように見せる TlbExp.exe でタプラブラリを生成 RegAsm でレジストリに登録 GACUtil /i: でGACに登録、またはゕプリケーションフォルダに配置 VS.NETでは[COM相互運用機能の登録]にチェック C:¥> TlbExp "MydotNetforCOM.dll" C:¥> RegAsm "MydotNetforCOM.dll" C:¥> GACUtil /I: "MydotNetforCOM.dll" .NET IFoo Managed Code (クラスラブラリ) COM Callable Wrapper IUnknown IDispatch Win32 Client IFoo コンポーネントの移行 ~ DLLは段階的に移行可能 ~ Win32 DLL, COM DLLのまま COM DLL : RCW 参照設定 Win32 DLL : P/Invoke Win32アプリ COM互換の.NETクラスラブラリを作成 .NETからも利用 Win32ゕプリからも利用 純粋な .NETクラスラブラリを作成 .NETからの利用に限定 Webサービスを作成する Win32ゕプリは Web Service Toolkitに より利用可能 .NETゕプリからはネテゖブに利用可能 他のシステム(JAVA,…)でも利用可能 .NETアプリ 実行時バンデゖング ~ .NETではリフレクションを利用! ~ COM : Late Binding VB だけの固有機能(互換性のため) Dim o As Object Set o = CreateObject("Project1.Class1") 'インスタンス化 o.WhoAreYou = "Masato Hirai" 'プロパティ Text1.Text = o.SayHello() 'メソッド呼び出し .NET : Reflection Imports System.Reflection Dim asm As [Assembly] = [Assembly].LoadFrom("Project1.dll") 'インスタンス化 Dim o As Object = asm.CreateInstance("Project1.Class1") 'プロパティ o.GetType().InvokeMember("set_WhoAreYou", BindingFlags.InvokeMethod, _ Nothing, o, New Object() {"Masato Hirai"}) 'メソッド呼び出し TextBox1.Text = CType(o.GetType().InvokeMember("SayHello", _ BindingFlags.InvokeMethod, Nothing, o, Nothing), System.String) Windowsメッセージの処理 ~ Windowsメッセージを直接処理することの是非 ~ .NETクラスラブラリで制御できないものに限る メッセージは可能な限り、System.Windows.Forms.Message クラスを利用してハンドルは、IntPtr型を利用する Const WM_NCLBUTTONDOWN As Long = &HA1 Const HTCAPTION As Long = 2 Dim msg As Integer = WM_NCLBUTTONDOWN Dim wParam As New IntPtr(HTCAPTION) Dim lParam As New IntPtr(0) Dim myMessage As System.Windows.Forms.Message 'Windowメッセージの作成 myMessage = System.Windows.Forms.Message.Create( _ Me.Handle, _ msg, _ wParam, _ lParam) 'マウスのキャプチャーを解放(=ReleaseCapure関数) Capture = False '自分のウィンドウプロシージャへ渡す(=SendMessage関数) WndProc(myMessage) VB6からVB.NETへの移行 ~ 簡単か難しいか? 作り直した方がいいのか? ~ VB6 から VB.NETへ移行は、他の言語よりも比較的容易だと言 えます。VS.NETに付属している「ゕップグレード ウゖザード」を 使えば機械的にソースコードを変換してくれます。しかし、その精 度とクオリテゖは完璧でないため、多少の修正作業が必要となりま す。「ゕップグレード ウゖザード」を使っても一部のActiveXコン トロールや描画関連コードなどゕップグレードできない部分も多く あります。 .NETでは生産性が飛躍的に向上しています。結局、再設計およ びスクラッチから作り直した方がよい場合がほとんどです。 ゕップグレード対策 ~ ほとんどは機械的に可能だが手直しが必要 ~ Code Advisor for Visual Basic 6.0 VB6のコードを分析して、.NETへ移行する際の改善点を提案する Visual Basic 6.0用のゕドンツール Visual Basic ゕップグレードウゖザード」 VB6のプロジェクト(*.vbp)のソースコードを.NET用に機械的 にコンバートするツール(VS.NETにバンドルされている) 機械的に移行できないもの DAOとRDOのデータバンデゖング(コードはOK) グラフゖックス関連(Line, Circle, Print, …) 印刷関連(Printerオブジェクト) Drag & Drop操作のコード Visual Basic 6 コードのゕップグレード コードエデゖタ上で VB6のコードを入力して.NET用のコードに変 換してくるゕドン 問題点リスト ~ VB6からの移行で何が問題になるか? ~ 致命度 ★★★★★ 致命度 ★★ 致命度 ★★ 致命度 ★★★★ 致命度 ★★★ 致命度 ★★★ 致命度 ★★★★ 致命度 ★★ 致命度 ★ 致命度 ★★ Printerオブジェクトは移行できない (印刷関連は壊滅) グラフゖックス命令 (Line, Print, PSet,..)は全滅 DataコントロールとRDCは移行できない (コードはOK) ADOコードはADO.NETでなくADOまま ADODCデータバンデゖングは互換ラブラリで対応 ActiveXコントロールは .NETコントロールに置換しない ActiveX コントロール(OCX)プロジェクトは移行できない コントロール配列は互換ラブラリで辛うじて対応 データ型の改修 (Variant→Object, Currency→Decimal, …) デフォルトプロパテゖが解決されない 言語仕様変更リスト ~ 細部にわたり注意が必要~ 致命度 ★★★★★ 致命度 ★★★★ 致命度 ★★★★ 致命度 ★★★ 致命度 ★★★★ 致命度 ★★★ 致命度 ★ 致命度 ★ 致命度 ★ 致命度 ★ 0 ベースの配列 (Dim arr(1 To 10) As Integerは不可) 固定長文字列変数の機構が変更 (Dim s As String * 10) xxxB関数(LenB, MidB, LeftB, RightB,…)は未サポート 変数のスコープがブロック単位 (For Each ) AutoRedrawは使えない (Paintベントへの移動) 引数は ByVal がデフォルト 構造化例外処理 (Try..Catch.. Finally, Throw) 直接メモリへのゕクセス禁止 (VarPtr, StrPtr, ObjPtr) ショートサーキット論理演算子 (AndAlso, OrElse)の新設 複合代入演算子(+=)、ビットシフト演算子(>>)の新設 移行手順 ~ どこまでコードを洗練させるか? 適度の妥協も必要? ~ ゕップグレードウゖザードによる機械的コンバート レポートを参考にコードを修正 とりあえずコンパルエラーが無くなるまでがんばる! 印刷、グラフゖックス、Drag&Dropなどの移行不能コードを改修 Option Explicit On / Option Strict On 未宣言変数を除去して型変換を強要させ、タプセーフなコードへ VB6固有の関数を撤廃 参照設定から"Microsoft.VisualBasic.Compatibility"を外す .NET Frameworkのクラスラブラリの関数を採用 Windows APIを撤去 ActiveXコントロールを .NETコントロールへ置換 コードの精査 新機能への切り替え コントロール配列 ~ "コントロール配列"はなくなったが、心配御無用! ~ 「ゕップグレード ウゖザード」ではVB6互換ラブラリ の"コントロールArray"クラスとしてコンバートされる VB 6と同じコーデゖングが可能だが、無理やり互換性を保つ構造 静的なコントロール配列の実装方法 ベントプロシージャの Handles 句に対象のベントを列挙 Private Sub TextBox_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter CType(sender, TextBox).BackColor = Color.Yellow End Sub 動的なコントロール配列の実装方法 AddHandler / RemoveHandler でベントプロシージャを脱着 AddHandler TextBox1.Enter, AddressOf TextBox_Enter AddHandler TextBox2.Enter, AddressOf TextBox_Enter Private Sub TextBox_Enter(ByVal sender As Object, ByVal e As …) 固定長文字列 ~ .NETには固定長文字列というデータ型はない ~ VB6互換ラブラリに代替クラスがある 参照 : Microsoft VisualBasic.NET Compatibility Runtime 実体 : Microsoft.VisualBasic.Compatibility.dll ンポート : Microsoft.VisualBasic.Compatibility.VB6 FixedLengthStringクラス VB6からの移行用なので可能な限り使わないほうがよい String型のもつメソッドがすべて利用できなくなる Valueプロパテゖによるゕクセス '// VB6 Dim s As String * 3 s = "ABCDEF" Debug.Print s 'ABC s = "あいうえお" Debug.Print s 'あいう '// VB.NET Imports Microsoft.VisualBasic.Compatibility.VB6 Dim s As New FixedLengthString(3) s.Value = "ABCDE" Console.WriteLine(s.Value) 'ABC s.Value = "あいうえお" Console.WriteLine(s.Value) 'あいう コントロール ~ 3つのパターンがある ~ UserControl クラスを継承して作成 [Windows コントロール ラブラリ] テンプレート 複合コントロールの作成が容易 ユーザー登録用コントロール、性別選択用コントロール、... Public Class UserEntryCtrl Inherits System.Windows.Forms.UserControl 既存のコントロールを継承して作成 数値入力用のテキストボックスやオーナードロー・リストボックス など... Public Class NumTextBox Inherits System.Windows.Forms.TextBox Control クラスを継承して作成 柔軟性はあるが描画を含むすべてコードを実装する必要がある Public Class MyGrid Inherits System.Windows.Forms.Control ASPからASP.NETへの移行 ~ 移行作業は大変だが効果は絶大 ~ ASPからASP.NETへの移行は、ほとんど書き直す作業が伴います。 HTML部分はそのまま流用できますがVBScriptまたはJScriptのサー バーサドのコードに関しては、大幅な修正を余儀なくされます。 ASPとASP.NETは同一のWebサーバー(IIS)で共存して稼動す ることができるため段階的に移行していくことも可能です。また、 Windowsゕプリケーションと同じコード、同じ手順、同じデバッ グ手法なので今まで VB6などWindowsゕプリケーションを開発し ていたエンジニゕでも容易にWEBゕプリケーションを構築できま す。 ASP.NET : 開発言語 ~ 1ページ内では単一言語 ~ ASP プログラミング言語として選択肢は"VBScript"か"JScript"のみ 同じページに複数言語によるスクリプトのブロックの混在が可能 <script language="vbscript" runat="server"> Response.Write "Hello VBScript." </script> <script language="jscript" runat="server"> Response.Write("Hello JScript."); </script> ASP.NET 同じページで複数言語によるスクリプトのブロックの混在は不可 VS.NETの場合はプロジェクト単位に開発言語を選択 <%@ Page Language="vb" Inherits="WebApplication1.WebForm1" %> <% Response.Write("Hello VB.NET.") %> 構造の変更 ~ 2つの大きな変更点 ~ <SCRIPT>ブロック内ですべてを宣言 NG <% <% RenderMe("Hello") %> RenderMe("Hello") Sub RenderMe(msg) Response.Write(msg) End SUB %> <script language="vb" runat=server> Sub RenderMe(ByVal msg As String) Response.Write(msg) End SUB </script> 表示機能の無効化 Response.Writeメソッドで文字列を出力するように修正 NG <%Sub RenderMe(msg)%> <H1><%= msg %></H1> <%End SUB%> OK <script language="vb" runat=server> Sub RenderMe(ByVal msg As String) Response.Write("<H1>" & msg & "</H1>") End SUB </script> API の変更 ~ Request APIの変更 ~ Request(item) Request.QueryString(item) Rewuest.Form(item) ASP : http://localhost/demo/test.asp?values=123&values=456 1ベースの配列 <% Response.Write Request("values") Response.Write Request.QueryString("values")(1) %> '123,456 '123 ASP.NET : http://localhost/demo/test.aspx?values=123&values=456 0ベースの配列 <% Response.Write(Request("values")) '123,456 Response.Write(Request.QueryString.GetValues("values")(1)) '456 %> VB言語仕様の変更 ~ VBの言語仕様変更に伴う影響はASP.NETにも! ~ Option Explicit が既定(変数宣言が必須) よくあるエラー Set, Let文 カッコなしの呼び出し デフォルト ByVal →省略しなければならない →括弧をつける →ByVal, ByRefを明示的につける Set cn = Server.CreateObject("ADODB.Connection") cn = Server.CreateObject("ADODB.Connection") MySubProc "Hello World." '←NG MySubProc("Hello World.") '←OK デフォルトプロパテゖの変更 Do Until rs.EOF Response.Write(rs(0)) Response.Write(rs(0).Value) rs.MoveNext() Loop '←NG '←OK '←NG '←OK ステート管理 ~ Session, Applicationオブジェクトは共有できない ~ ASPとASP.NET間で共有できない 一貫したセッション管理下ではASPかASP.NETのどちらかに統一 ASP.NETのステート管理 web.configフゔルの<sessionState>セクションで設定 "InProc", "StateServer", "SqlServer", "Off" の4種類 COMコンポーネントの参照をセッション変数に格納する場合は "InProc"(デフォルト)のみ有効 <!-- セッション状態の設定 --> <sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="20" /> COM関連 ~ ASP.NETからCOMをコールする場合 ~ スレッドモデルの変更 ASP.NETは"MTA"(マルチスレッドゕパートメントモデル) VB6で作成したCOMやADOなどは"STA"(シングルスレッドゕ パートメントモデル) aspCompat="True" <%@ Page aspCompat="True" %> ASP.NETを"STA"モードで実行させるオプション パフォーマンスが若干低下するため必要時のみ Early Binding(事前バンド)への変更 Late Binding(実行時バンデゖング)でも動作する Dim rs1 As New ADODB.Recordset '// 事前バインディング rs1.Fields.Append("F1", ADODB.DataTypeEnum.adVarChar, 10) Dim rs2 As Object '// 実行時バインディング rs2 = Server.CreateObject("ADODB.Recordset") rs2.Fields.Append("F1", ADODB.DataTypeEnum.adVarChar, 10) 移行手順 ~ はじめは小さいページから挑戦しよう! ~ Visual Studio [既存項目の追加]で ASPフゔルを追加 拡張子を変更 ".asp" → ".aspx" <%@ Page %>デゖレクテゖブをHTMLの冒頭に追加 Language = "vb" Codebehind = "demo.aspx.vb" Inherits = "MyApps.WebForm1" プロジェクトをコンパル タスクリストの指示に従って問題を逐次修正 スクリプトブロックの構造上の問題を解消 変数のデータ型を宣言 事前バンデゖングへの切り替え ラウンドトリップ型への改造 ASP.NETのWebコントロールへの切り替え 『1から作り直した方が良い場合が多い』 ADOからADO.NETへの移行 ~ そのまま使うか? ADO.NETに書き直すか? ~ ADO.NET はADOの利点を引き継ぐとともにADOの欠点と指摘されてい た階層間データ転送の仕組みを改善し、データソースとの関係を明確に分 離した非接続モデルを採用しました。ADO.NETは、ADOと「似て非なる もの」ですが、ンターネットおよびn階層ゕプリケーションの構築に必 要な要件がすべて備わっています。 ADOのコードは、COM互換機能により.NETマネージドコードからもそ のまま利用できますが、ADO.NETのパフォーマンスとスケーラビリテゖ は特筆すべきものがあります。移行作業の中でADO.NETへの書き直しは、 もっとも効果が大きい部分なのです。当然ながら、ADO.NETのメリット を最大限に活用するには、データゕクセスの設計を見直す必要もあります。 データゕクセス・テクノロジーの進化 ~ 時代とともにニーズは変わる ~ DAO RDO ADO.NET ADO Data Provider RDS OleDb Sql Oracle ODBC OLE DB Jet Engine DASQL Jolt SQL ORA … ODBC Jet Access Excel SQL ORA … Excel SQL Server Oracle XML 新しいデータゕクセスの必要性 ~ またしても新しいデータゕクセス・テクノロジー ~ ADOの問題点と課題 すべての階層でCOM/DCOMが利用できる環境とは限らない 他のプラットフォームを含む分散環境でデータ伝送の手段がない ンターネット上でRecordsetをやり取りすることは困難 リソース集約型でスケーラビリテゖに欠ける Presentation Tier COMのマーシャリング コストが高い Windows Apps XMLのサポートが不完全 データソースに依存したプログラミング Business Tier Data Store Data Tier COM DCOM ADO Recordset ADO Recordset DCOM DCOM Presentation Tier Web Apps IIS ASP HTTP ADO.NETの概要 ~ ADO.NETのポントはここだ ~ ンターネットを意識した非接続型モデル 階層間でデータ転送が容易 異なるゕプリケーション/システム間でXMLによるデータ交換 パフォーマンスとスケーラビリテゖを大幅に向上 XMLをネテゖブにサポート XMLからの読み込みとXMLへの書き出しをサポート DOM, XSD, XSLTなどのXML機能を統合 DataSet クラスの新設 リレーショナルデータベースのローカルコピー XMLによる永続化と復元が可能 複数テーブルを格納でき、そのリレーションシップや制約も管理 データプロバダとデータセットの分離 実際のデータソースへのゕクセスはデータプロバダが担当 データソースに依存しないデータ操作はデータセットが担当 ADO.NETのゕドバンテージ ~ ADO.NETにすると何が良くなる? ~ 相互運用性 XMLでのデータ表現 システム間・階層間をXMLでデータ転送 スケーラビリテゖ 非接続型モデルを改善 更新メカニズムの刷新 強い型付け コードの信頼性 Presentation Tier Windows Apps Business Tier HTTP TCP/IP HTTP TCP/IP Data Store Data Tier DataSet Presentation Tier DataSet IIS ASP.NET HTTP ADO.NETのオブジェクトモデル ~ データソースに依存する部分をデータプロバダに封じ込めた ~ データプロバイダ DataAdapter DataReader DataRelation SELECT UPDATE Command Parameter Connection データセット INSERT DataRow DELETE DataColumn Transaction DATA STORE DataTable DataView XML / XSD ADOとADO.NETの比較 ~ 違いは結果セットの表現が COMバナリか標準XMLか ~ ADO ADO.NET ゕーキテクチャ COM コンポーネント .NET ベースクラス モデル 常時接続モデル クラゕント / サーバー 非接続モデル ンターネット / 分散環境 スケーラビリテゖ 低い 高い 階層間のデータ転送 COMバナリ XML データ転送プロトコル COM / DCOM TCP/IP, HTTP XMLサポート あり(独自フォーマット) あり(W3C標準) XSD, XSLTサポート なし あり カーソル Server/Client カーソル カーソルの概念なし レコードの走査 MoveNext MoveXXXX DataReader: Readメソッド DataSet: Rows コレクション ンターネットで使用 △ RDS (IE限定) ○ HTTP/XML データソースとの関連 密 疎 ADOとADO.NETの比較 ~ カーソルという概念はもはやADO.NETにはない ~ ADO ADO.NET 複数テーブルの管理 不可 可能(DataSet クラス) 結果セット管理 Recordset オブジェクト DataTable オブジェクト DataReader オブジェクト (SqlResultSetオブジェクト) リレーションシップ (JOINクエリーで処理) Relation オブジェクト 接続 Connection オブジェクト xxxConnection オブジェクト コマンド Command オブジェクト xxxCommand オブジェクト パラメータ Parameter オブジェクト xxxParameter オブジェクト 行へのゕクセス (カーソル) EOF, BOF 判定 DataRow オブジェクト コレクション ループ 列へのゕクセス rs.Fields("Name") rs.Fields(0) Rows(0).Item("Name") Rows(0).Item(0) Customer(0).Name トランザクション cn.BeginTrans メソッド xxTransaction オブジェクト データ取得の比較 ~ オブジェクトにとって微妙に違う ~ ADO – Recordset カーソル操作(MoveNext) EOF 判定 Fieldコレクション Do Until rs.EOF For n = 0 To rs.Fields.Count - 1 Response.Write(rs(n).Value) Next rs.MoveNext() Loop ADO.NET – DataReader シーケンシャルなゕクセス Readメソッド While rd.Read() For n = 0 To rd.FieldCount - 1 高速 Response.Write(rd(n).ToString()) 軽量 Next End While シリゕラズ不可 ADO.NET – DataSet コレクション操作 やや低速 シリゕラズ可能 Binary, SOAP-XML For Each r In ds.Tables(0).Rows For Each c In ds.Tables(0).Columns Response.Write(r.Item(c).ToString()) Next Next DataAdapterクラス (データプロバダ) ~ 結果セットの取得および更新を管理するクラス ~ ポント データソースからデータセットにデータを充填(Fillメソッド) SqlDataAdapter dap = new SqlDataAdapter("SELECT * FROM authors", cn); DataSet ds = new DataSet("MyDs"); dap.Fill(ds,"authors"); データセットの変更をデータソースに反映(Updateメソッド) CommandBiulderクラスにより更新コマンドの自動生成も可能 DataSet DataAdapter Fill Select UPD INS DEL Update Connection SqlDataAdapter dap = new SqlDataAdapter("SELECT * FROM authors", cn); DataSet ds = new DataSet("MyDs"); ds = (DataSet) this.dataGrid1.DataSource; SqlCommandBuilder cb = new SqlCommandBuilder(dap); dap.Update(ds, "authors"); DATA STORE データセットの更新 ~ ンテリジェンスな更新メカニズム ~ 第1段階 – DataSetに対しての更新(非接続) 変更前の 追加: NewRow → Rows.Add(row) データを 修正: BeginEdit → 変更 → EndEdit 保持 削除: Rows(n).Delete() 現バージョン(Current)に対して追加・修正・削除 Original 元バージョン(Original)が作成される WHERE句パラメータ用 Current F1 F2 RowState 1 AAA Unchanged 2 BBB Unchanged 3 CCC Unchanged F1 F2 1 AAA 2 BBB Current 修正 削除 追加 F1 F2 RowState 1 XXX Modified 2 BBB Deleted 3 CCC Unchanged 4 ABC Added データソースの更新 ~ 今までになかった考え方 ~ 第2段階 – DataAdapterでデータソースに反映(要接続) DataAdapter.UpdateメソッドにDataSetを渡す DataAdapterの各更新Commandが実行される 現バージョンの値が SET 句パラメータにセット Current 元バージョンの値がWHERE句パラメータにセット F1 F2 RowState 1 XXX Modified 2 BBB Deleted F1 F2 3 CCC Unchanged 1 AAA 4 ABC Added 2 BBB Original UPDATE MyTB SET F1 = @F1, F2 = @F2 WHERE (F1 = @Original_F1) AND (F2 = @Original_F2) DATA STORE DataAdapter UPDATE INSERT INTO MyTB (F1, F2) VALUES (@F1, @F2) INSERT DELETE FROM MyTB WHERE (F1 = @Original_F1) AND (F2 = @Original_F2) DELETE バッチ更新のサンプル ~ いかにT-SQLを簡略化してデータ転送量を抑えるか! ~ Dim adp As New SqlDataAdapter("SELECT * FROM Sample1", cn) adp.InsertCommand _ = New SqlCommand("INSERT INTO Sample1 (F2, F3) VALUES (@F2, @F3)") adp.InsertCommand.Parameters.Add( _ New SqlParameter("@F2", SqlDbType.Int, 4, "F2")) adp.InsertCommand.Parameters.Add( _ New SqlParameter("@F3", SqlDbType.VarChar, 10, "F3")) adp.DeleteCommand = New SqlCommand("DELETE FROM Sample1 WHERE F1 = @F1") adp.DeleteCommand.Parameters.Add( _ New SqlParameter("@F1", SqlDbType.Timestamp, 8, "F1")) adp.UpdateCommand _ = New SqlCommand("UPDATE Sample1 SET F2=@F2, F3=@F3 WHERE F1=@F1") adp.UpdateCommand.Parameters.Add( _ New SqlParameter("@F2", SqlDbType.Int, 4, "F2")) adp.UpdateCommand.Parameters.Add( _ New SqlParameter("@F3", SqlDbType.VarChar, 10, "F3")) adp.UpdateCommand.Parameters.Add( _ New SqlParameter("@F1", SqlDbType.Timestamp, 8, _ ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), _ "F1", DataRowVersion.Original, Nothing)) adp.UpdateBatchSize = 100 adp.Update(ds.Tables(0)) .NETでADOを使う ~ .NETマーネジコードからADOの利用も可能 ~ .NETでもADOは使える 短期的なソリューション 暫定的なステップ .NET ラッパークラス(adodb)への 参照設定が必要 ADOコードからADO.NETコードへ VBのUpgrade Wizardでは、ADOはADOのまま ASP 内のスクリプトは手作業で移行 ADOのRecordsetをADO.NETのDataSetに変換可能 既存COMコンポーネントとの相互運用に便利 OleDbDataAdaper.Fill メソッド OleDbDataAdapter1.Fill(ds.Tables[0], rs); 逆は DataSet → XMLフゔル → Recordset ADO.NETでの排他ロック ~ 使うなと言われると余計に使いたくなる ~ BeginTransaction にIsolationLevel.Serializableで開始 RollBack, Commitメソッドで解除 CommandオブジェクトのTransactionプロパテゖにセット ※ 同時実行性が極度に低下してスケーラビリティに大きな影響を与えます Dim cmd As New SqlClient.SqlCommand() cmd.CommandText = "SELECT au_lname FROM Authors" cmd.Connection = cn Dim tx As SqlClient.SqlTransaction tx = cn.BeginTransaction(IsolationLevel.Serializable) Dim rs As SqlClient.SqlDataReader cmd.Transaction = tx rs = cmd.ExecuteReader(CommandBehavior.CloseConnection) MessageBox.Show("この段階で更新ロックがかかっています!") While rs.Read() System.Diagnostics.Debug.WriteLine(rs.GetString(0)) End While rs.Close() MessageBox.Show("まだ更新ロックがかかっています!") tx.Rollback() データゕクセスの最適化 ~ 生かすも殺すもプログラマの腕の次第 ~ DataAdapterによるバッチ更新 行を特定するWHERE句の条件を最小限に! 全カラム比較を避ける UpdateBatchSizeプロパテゖの設定 規定は 1 なので一度に複数行を変更するにはサズを大きくする 更新用のDataSetを伝播させる場合は、変更行のみに圧縮 行を返さないクエリーは ExecuteNonQuery メソッド 更新された行数のみ返す スカラー値の取得は ExecuteScalerメソッド COUNT, SUM,..などでSELECTで単一値を取得する場合に高速 なるべくゕセンブリにT-SQLを埋め込まない ストゕドプロシージャの利用 T-SQLで処理できることはT-SQLで記述すべし 移行手順 ~ かなりの部分は書き直しなるが効果は絶大! ~ 事前調査と検討事項 データバンデゖング コントロール DAO, RDCデータコントロールの利用状況 .NETマネージドプロバダが提供されているか 常時接続でのRecordsetに対する更新処理があるか ADO.NETではバッチ更新が原則 DataSetを利用するかDataReaderでフェッチするか 同時実行違反に対する対策 ADOのままにするかADO.NETに書き直すかを決定 暫定的な.NET対応であればADOのままでよい コードの修正作業 部分的に出来ないので一気に修正作業を行う パフォーマンスや動作検証をしっかり テスト期間は長めにとる 参考資料 『ADO プログラマのための ADO.NET』 http://www.microsoft.com/japan/msdn/net/upgrade/adonetprogmsdn.asp 『Microsoft Win32 と Microsoft .NET Framework API』 http://www.microsoft.com/japan/msdn/net/general/win32map.asp 『Visual Basic 6.0 から Visual Basic .NET への移行』 http://www.microsoft.com/japan/msdn/vbasic/techinfo/upgrade/transition/default.asp 『Visual Basic .NET ゕップグレード ガド』 http://www.microsoft.com/japan/msdn/vbasic/techinfo/upgrade/guide.asp 『ASP から ASP.NET への変換』 http://www.microsoft.com/japan/msdn/net/upgrade/convertasptoaspnet.asp 『ASP.NET に移行する際の主な検討事項』 http://www.microsoft.com/japan/msdn/net/aspnet/aspnetmigrissues.asp 『Visual Basic 6.0 と .NET のコントロールの相違点』 http://www.microsoft.com/japan/msdn/net/upgrade/actxvnetcontrols.asp 参考資料 『Visual Studio Tools for the Microsoft Office System の紹介』 http://www.microsoft.com/japan/msdn/vstudio/office/productinfo/features/officetools.asp 『Visual Basic .NET におけるオブジェクト指向プログラミング』 http://www.microsoft.com/japan/msdn/vbasic/techinfo/upgrade/programming.asp ダウンロード 『Code Advisor for Visual Basic 6.0 - 日本語版』 http://www.microsoft.com/japan/msdn/vbasic/downloads/codeadvisor/default.asp まとめ Win32ゕプリケーションを.NET Frameworkに対応さ せるための移行作業は簡単なのでしょうか? 答えは"NO"です。.NETへの移行は実際それほど単純で ありません。VB6に関しては「ゕップグレード ウゖザー ド」を使って機械的にソースコードを変換することがで きますが、100%完璧ではありません。 移行作業をスムーズに行うためには、現行資産を慌てて ゕップグレードする前に先にエンジニゕの方々を.NETへ シフトしておかなければなりません。移行作業にはどう しても.NETを熟知したエース級のエンジニゕが必要とな ります。 いづれにしても.NETのハードルは高いですが予想以上 の効果が期待できますので、早めにご対応下さい。 Questions and Answers ! これは? あれは? ウゲェ~ なんで? Thanks for Attending ! ゕンケートにご協力ください。
© Copyright 2024 Paperzz