もぅタイトル通り。
なのでスクリプト内部でデータやオブジェクトの存在チェックして~、という手法が全く使えません。解決策としては・・・それようのAPを用意することくらいなんだよねぇ。
まぁCompactはそういう用途向けだからいいといえばいいな。
DataGridView や DataRepeater にこだわりつつ
時代は Workflow Foundation などと言い続けていたら
これからは LogicFlow だろ! と思い始めてきた
色々浅く広くやっていく古い技術者の Blog
もぅタイトル通り。
なのでスクリプト内部でデータやオブジェクトの存在チェックして~、という手法が全く使えません。解決策としては・・・それようのAPを用意することくらいなんだよねぇ。
まぁCompactはそういう用途向けだからいいといえばいいな。
ちょっとイメージと違ったのでメモ。
Parallelと言われるとマルチスレッドよろしく、複数処理の並行動作をイメージしているんだけど、WFのParallelはそういう非同期ではなかったのね。

検証するために上記のようなワークフローで試してみた。whileActivityでは単純に10回ループさせるようにし、各codeActivityではConsole.WriteLineしてみる。この場合、DelayActivityがなければ、
1→2→3→4 とか 2→1→4→3とか
こういった形で「シーケンシャル」に処理が実行された。図のように間にDelayを挿入して適当な時間待たせるようにすると、
1→2→4→3 とか 2→1→4→3とか
CodeActivity3の前に別Activityの処理が行われるようになった。こんな感じで
処理の順番が保障されない
という意味合いでのパラレルだった。
うーん、さすがにマルチスレッド動作を願ったのは高望だったなw
タイトル長いw
まぁ今となってはこんな事をする奇特な人は少ないだろうけど、自分がその一人なのでメモとして。
3.0SP1以降のFrameworkがセットアップされていると、このWPFエクステンションはそのままではセットアップができない仕様になっています。対応策は二つあって、一つはレジストリを書きかえるとのこと。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{15095BF3-A3D7-4DDF-B193-3A496881E003}]
"DisplayName"="Microsoft .NET Framework 3.0"
でももう一つの方が楽なのでこっちを使うことに。
msiexec /i vsextwfx.msi WRC_INSTALLED_OVERRIDE=1
コマンドプロンプトからmsiを実行するようにして、その際にオプションを指定すればOK。新しい環境でVS2005を使う人でなおかつそいつでWPFやWCF触ろうという奇特な人はメモですね。
Asp.Netの環境構築で必須なのは、
「IIS→.Net Frameworkの順序でインストール」
この順序。こうしなければASP.NETの設定が出来ても動作しない(AppDomainの生成でエラー、等がイベントログにたんまり発生する)。昔は.Net Frameworkも手動やセットアップ(msi)にてインストールだったのでそれほど問題じゃなかったんだけど、今のご時世ほぼ全ての環境で.Net Frameworkはインストール済み。
つまりこの状態でIISを設定してもAsp.Netは動作しない環境になってしまうことに・・・。
ここで必要なのがIISへAsp.Net登録。バッチファイル一発なので必須作業として行う必要があるかと。
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe –i
これからは絶対必須。忘れないようにメモメモ・・・。
前回がファイル・フォルダの同期だったので今回はデータベースの同期にチャレンジ。ただ、やろうと思うと結構難しいところがでてくる(異種DBとか)ので、今回はダンプファイルからリストアよろしく、親DBの内容を子DBに単純コピーする程度でやってみた。
ちと長めになるけどこんなソース。
Private Sub DbSync()
Const SCOPE_NAME As String = "SCOPE1"
Const SCHEMA_NAME As String = "" '"Sync"
Const PREFIX_NAME As String = "Sync"Dim sourceProvider As New SqlSyncProvider
Dim destinationProvider As New SqlSyncProviderDim srcStr As New SqlConnectionStringBuilder
Dim desStr As New SqlConnectionStringBuilder
With srcStr
.DataSource = "TESTSERVER"
.InitialCatalog = "TESTDB"
.PersistSecurityInfo = True
.IntegratedSecurity = True
End With
With desStr
.DataSource = "TESTSERVER"
.InitialCatalog = "TESTDB2"
.PersistSecurityInfo = True
.IntegratedSecurity = True
End WithUsing srcConn As New SqlConnection(srcStr.ToString)
Using desConn As New SqlConnection(desStr.ToString)
'変更追跡用テーブルを生成
Dim serverScope As New DbSyncScopeDescription(SCOPE_NAME)
'対象テーブル一覧の取得
Dim query As String = "SELECT NAME, OBJECT_ID FROM SYS.TABLES"
Using sqlAdapter As New SqlDataAdapter(query, srcConn)
Using tblSet As New DataTable
sqlAdapter.Fill(tblSet)
For Each child As DataRow In tblSet.Rows
If child.Item(0).ToString.Contains(PREFIX_NAME) Then Continue ForDim targetTable As DbSyncTableDescription = _
‘同期の設定
SqlSyncDescriptionBuilder.GetDescriptionForTable(child.Item(0).ToString, srcConn)
serverScope.Tables.Add(targetTable)
Next
End Using
End Using
Dim serverConfig As New SqlSyncScopeProvisioning(serverScope)
With serverConfig
.ObjectSchema = SCHEMA_NAME
.ObjectPrefix = PREFIX_NAMEIf Not .ScopeExists(SCOPE_NAME, srcConn) Then
.SetCreateTableDefault(DbSyncCreationOption.Skip)
.Apply(srcConn)
End IfEnd With
Dim clientScope As DbSyncScopeDescription = _
SqlSyncDescriptionBuilder.GetDescriptionForScope(SCOPE_NAME, PREFIX_NAME, SCHEMA_NAME, srcConn)
Dim clientConfig As New SqlSyncScopeProvisioning(clientScope)
With clientConfig
.ObjectSchema = SCHEMA_NAME
.ObjectPrefix = PREFIX_NAMEIf Not .ScopeExists(SCOPE_NAME, desConn) Then
.Apply(desConn)
End If
End WithWith sourceProvider
.ScopeName = SCOPE_NAME
.ObjectPrefix = PREFIX_NAME
.ObjectSchema = SCHEMA_NAME
.Connection = srcConn
End With
With destinationProvider
.ScopeName = SCOPE_NAME
.Connection = desConn
.ObjectPrefix = PREFIX_NAME
.ObjectSchema = SCHEMA_NAME
End With
‘同期処理の実行
Dim syncAgent As New SyncOrchestrator
With syncAgent
.RemoteProvider = sourceProvider
.LocalProvider = destinationProvider
.Direction = SyncDirectionOrder.Download
.Synchronize()
End WithEnd Using
End Using
MessageBox.Show("DBの同期が終了しました。", My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
とりあえずこのくらいのロジックで、DB間にてレコードの同期を取ることができた。
気を付けるのは、レコード間の同期を取るために専用のテーブルやトリガ、ストアドプロシージャが必要になるんだけど、それはSqlSyncScopeProvisioning.Applyメソッド呼び出し時に作成してくれる。この時このサンプルのようにスキーマを設定していないと、同一スキーマに作成される=同一権限の人にはテーブルやらがたくさん増えて見える、ことになるのが注意。スキーマを予め用意しておけば、切り離して見ることができるのでそれがベター、というかベストだろうねぇ。
残念ながらスキーマまでは作成してくれませんw
いろいろあってSync Frameworkによる同期について調査。
とりあえず、でやってみたのは「ファイルの同期」。SyncToyとか使ってやればいいんだけど勉強と調査をかねてやってみた。
結論から言うと「物凄く簡単にファイル同期ができる」というところに。
注意すべきところは
「参照設定で個別にSyncFrameworkのDllを設定する必要がある」
点かな。今回のファイル同期であれば、
これらはSyncFramework2.0をインストールすると、ProgramFiles関係のフォルダにインストールされているのでそこから直接参照しないといけないのよ。GACに入っていると思っていたから少し探してしまった。
'同期オプションの指定
Dim syncOption As FileSyncOptions = FileSyncOptions.CompareFileStreams Or FileSyncOptions.ExplicitDetectChanges Or FileSyncOptions.RecycleConflictLoserFiles Or FileSyncOptions.RecycleDeletedFiles
'対象ファイルの設定(今回未使用)
Dim syncFilter As New FileSyncScopeFilter
With syncFilterEnd With
'同期処理の実行
Using src As New FileSyncProvider(コピー元, Nothing, syncOption)
Using dest As New FileSyncProvider(コピー先, Nothing, syncOption)src.DetectChanges()
dest.DetectChanges()Dim syncAgent As New SyncOrchestrator
With syncAgent
.RemoteProvider = src
.LocalProvider = dest
.Direction = SyncDirectionOrder.Download
.Synchronize()
End WithEnd Using
End Using
以上がファイル同期に書いてみたソースの全部。これだけで楽々できてしまうので、業務システムとかでよくある最新モジュールの適用などは大分楽にできるようになるねぇ。もちろんセキュリティ関係とか処理タイミングとか考えないといけないことが多々あるので、そこらへんは一工夫。
64ビット版のみとなった2008R2で、VB6アプリがどうなるかを自分の案件に限って動作確認してみた。あくまでもメモ。何かあっても責任は一切ないw
基本そのまま動く。もちろんパスのハードコーディングとか「今更か!」というヤカラはなしにして。予想していたよりもWow64はすごい。
自分の案件では某社のDenpyoManとActiveReport。まぁこれも特に問題なく動作してしまったw
未だに動作する環境でリリースするMicrosoftはとてもすごいよねぇ。もし自分がオーナーとかPMだったら、とっくに動作対象外にしてばっさりと切り捨てているだろうし。
インストールの際に利用しているコントロールによっては管理者権限が必須。Tabとかフレックスグリッドとか。それ以外なら恐らく標準ユーザーでもいけるんじゃなかろうか。
最近は仕事の合間にWPFを研究するようにメンバーに指示を出しているので、自分も負けじと勉強中。わかってはいたんだけど、改めてWPFのスゴサに感動気味。
伝票形式のグリッド?何それ、WPFならラクショーじゃんw
いやぁ・・・軽く触っただけで多段レイアウトの一覧表示がさくっと作れるというのは業務系システムにこそ、メリット大きいよなぁ。正直WindowsFormsを利用し続ける事に意義が見出せなくなるぐらい・・・。
まだWPFやっていない人にとっては時間もかかって大変だろうけど、かけた時間以上の効果が間違いなくWPFにはあるねぇ。今からでも遅くないからやるべきだわ。
一番問題なのはウチの社内みたいに、データバインディングも使っていない、場合なんだよねぇw
さてさてどうしましょ。
実際には含まれていないw
ということで自作してみる。
ConnectionBuilderはSystem.Data.Common.DbConnectionStringBuilderを継承して作ればいいので、基本的な部分はほとんど実装することないんだよね。他のConnectionBuilderの実装を見たわけではないんだけど、恐らくはここらへんをクリアしてれば十分かと。
初期値についてはMSDNとかTechNetを見てもらえば記載されているのでそれを転記。あとは接続文字列出力部分、なんだけどそのメソッド自体は特にどうこうしなくてもいいのよね。
設定の保持方法を他と合わせてあげればOK。実際にはDbConnectionStringBuilderにて用意されているHashTableに値を追加したり削除したりするよう、プロパティの実装をやってあげればOK。