PDF 形式

既存資産の.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 !
ゕンケートにご協力ください。