uso

雑記いろいろ
★書いてある内容に保証は一切ありません。
 ご自身で判断をしてください。

[.net] VB.net小ネタ 2/2

2010-12-17 10:46:42 | work
■ ListBoxのデータの並びを降順にする
  
  ListBoxを昇順にするには、
  ListBox.Sorted = True

  降順にするには・・・
    ListBox.Sorted = True              '昇順に並べる
    ArrayList.Adapter(ListBox.Items).Reverse() '値を反転(降順)
    ListBox.Sorted = False             '値が昇順にならないようにする

  参考:http://hanatyan.sakura.ne.jp/dotnet/list02.htm#no7

  値が多くなると遅くなるらしいので、どうしたものか・・・。


■ OleDBを使ったトランザクション処理

  参考:http://msdn.microsoft.com/ja-jp/library/aa325885(v=VS.71).aspx
  
  大体この辺のやり方でトランザクション処理を作り、更新ロックをかけてみたら、
  エラー「分離レベルおよびその強化はサポートされていません。」
  
  調べてみると、Jet.OLEDB.4.0プロバイダのトランザクション分離レベルについて、
  参考:http://d.hatena.ne.jp/hilapon/20100701/1277984287

  上記サイト抜粋
  「Jet 4.0 OLE DB プロバイダ で MDB ファイルに接続した場合、トランザクション分離レベルで指定できるのは、
   IsolationLevel.ReadUncommitted か IsolationLevel.ReadCommitted の二種類のみ可能なようです。」

  「RepeatableRead や Serializable を指定すると、System.Data.OleDb.OleDbException
   "分離レベルおよびその強化はサポートされていません。"」
  
  Serializable がしたいんですけどっ・・。
  

■ Jet 4.0 OLE DB で更新ロック
  
  Oledbでの更新ロックができないとわかり、常套句のFor Updateでもしちゃおうかな、と思ったら、
  Accessにはありません・・・。
  ええっ、と思ったが、ロックかけるほど大規模なのってAccess使わないっしょ、という、
  調べた掲示板の書き込みに、うなずいてしまった。。
  
  おお、どうしよう・・・って事で粘ってみた。
  Accessにだってロック機能はある、はず。ありました。
  
  参考:http://msdn.microsoft.com/ja-jp/library/cc426819.aspx
  ↑ プロバイダ固有の接続パラメータにある、
  「Jet OLEDB:Database Locking Mode」

  ページロックがJet OLEDB:Database Locking Mode = 0
  行ロックが   Jet OLEDB:Database Locking Mode = 1
 
  この設定は、Openすると変えられない、らしい。
  (一部参考:http://homepage1.nifty.com/MADIA/vb/vb_bbs2/200509/200509_05090130.html)

  パラメータ説明はここ:http://msdn.microsoft.com/ja-jp/library/dd263027.aspx
  
  だが、書き方がわからず手間取る・・・。
  とりあえず、OleDbConnectionStringBuilder クラスの説明で、たまたまこのロック制御をしている例文が有ったので、
  参考:http://msdn.microsoft.com/ja-jp/library/system.data.oledb.oledbconnectionstringbuilder.aspx

  そこのソースをデバッグで実行して、BuilderのConnectionStringを見る、という強行手段。

  ";Jet OLEDB:Database Locking Mode=1"

  これを、ConnectionのConectionStringsに追加する。
  
  さて、デバッグ状態で接続、テーブル開いたところまで行き、Accessからテーブル更新してみる。
  普通はできないはず・・・できます。ロックしてない・・・?
  
  Accessコンソールでやってるから意味無いのか??
  と思い、別のプロジェクトからつないだり更新してみると、できる。
  やはりロックされていない。。。泣けてきた。

  ???と悩み、時間を無駄にしながら下記サイトの記述が気になる。
  http://msdn.microsoft.com/ja-jp/library/cc376645.aspx
  
  「Microsoft Jet 4.0 OLE DB Provider で ADO を使用し、Access データベースで作業する場合は、
   データベースを開く前に Connection オブジェクトにあるプロバイダ特定の
   Jet OLEDB:Database Locking Mode プロパティを設定し」

  「次に SQL DML ステートメントの実行、または Recordset オブジェクトを開く/返すメソッドに使用する
    Recordset オブジェクトのプロバイダ特定の Granularity プロパティを設定します。」

  ってな事で、Granularityプロパティを調べる。
  
  設定方法は、
  objRecordset.Properties("Jet OLEDB:Locking Granularity").Value = 2
  (1がページロックで2が行ロック)
  参考:http://www.gizcollabo.jp/vbtomo/log/archive/vbdatabase_1483_0.html

  んで、今回使っているのが、OleDb.OleDbDataReader。
  どーやって設定すんの・・・?
  
  で、挫折。。。
  Locking ModeみたいにConnectionStringに直接入れてみたが、エラー。
  今回ばかりはGoogle先生も教えてくれない。
  
  ただ、http://msdn.microsoft.com/ja-jp/library/cc426819.aspxをじっくり読んでいると、
  :Locking GranularityとLocking Modeはパラメータだが、使いどころが違うらしい。

  Locking Modeは、
  「Connection オブジェクトの Properties コレクションで設定するか、
   接続文字列の一部として設定することができます。」

  だが、Locking Granularityは、  
  「Recordset および Command に関するプロバイダ固有の各種プロパティをサポート」で
  「プロパティの取得および設定は、Recordset オブジェクトまたは Command オブジェクトの
   Properties コレクションを通  して行います。」

  思っているものとは違うらしいし、ConnectionStringに設定するものでもないらしい。。

  参考:http://bbs.wankuma.com/index.cgi?mode=al2&namber=18719&KLOG=36

  この期に及んで、ADODB.Recordsetを使うの??
  接続から全て変更しなければ 。゜(゜´Д`゜)ノ。。
  
  まあ・・・行ロック用のフィールド追加してしまったほうが早いか・・・。


[.net] VB.netの文字コード色々

2010-12-14 15:33:00 | インポート
■ 文字コードの扱い
  
  VB.netは文字をUnicodeで扱う。なので、全て2バイト、
  「あ」も「0」も「a」も全て2バイト(らしい)。
  Accessも新しいバージョンはそう。
  
  そんなことも知らず、全角30文字で半角60の60バイト入力でいいですか~?
  と適当に仕様を決めてしまった自分が恨めしい。

  仕方ないので、いちいちs_jis二変換してバイト数数えて、バイト単位で切って・・・
  
■ MidB(対処文字列 , 開始(1~) , 切り取りたいバイト数)関数
  
  VB6ではこれで簡単に文字列をバイト単位で切ることができた。らしい。よく知らないのだが・・・。

  参考:http://jeanne.wankuma.com/tips/vb.net/string/leftb.html
     :http://homepage1.nifty.com/rucio/main/dotnet/Samples/Sample068MidB.htm←こちらを読みながら作成
      ・・・させてもらったが、最後の2バイト文字判定に?があったので、自分なりに改良。
        自分なりに読んで作ったから、ただのコーディングミスだと思うが、原因がわからず危うい。。。

  コード
    '-----------------------------------------------------
    '文字列切り取り(半角・全角混在)
    '引 数:str(切り取る文字列)
    '   :start(開始位置 1~)
    '   :length(切り取る文字数)
    '戻り値:切り取った文字列(String)
    '機 能:文字列を1バイト単位で指定して切り取る
    '-----------------------------------------------------
    Public Function MidByte(ByVal str As String, ByVal intStart As Integer, ByVal intLength As Integer)

        Dim intCount As Integer
        Dim resCount As Integer
        Dim s_jis As System.Text.Encoding
        Dim bytStr() As Byte
        Dim strAsc As String

        '空白文字
        If str = "" Then
            Return ""
        End If

        s_jis = System.Text.Encoding.GetEncoding("shift-jis")

        '文字のバイト数取得
        intCount = s_jis.GetByteCount(str)

        '指定文字数が0もしくは、Start以降のバイト数をオーバーする
        '場合はStart以降の全バイトが指定されたものとみなす
        resCount = intCount - intStart + 1
        If intCount = 0 OrElse resCount < intLength Then
            intLength = resCount
        End If

        'バイト変数作成
        bytStr = CType(Array.CreateInstance(GetType(Byte), intLength), Byte())

        '切り抜き
        Array.Copy(s_jis.GetBytes(str), intStart - 1, bytStr, 0, intLength)

        '最後の文字が全角バイト文字の後半だった場合、最後の文字を切り捨てる

        strAsc = s_jis.GetString(bytStr)

        If Asc(Strings.Right(strAsc, 1)) = 0 Then
            'VB.NET2002,2003の場合、最後の1バイトが全角の半分の時
            Return strAsc.Substring(0, strAsc.Length - 1)
        ElseIf intLength = resCount - 1 And Asc(Strings.Right(strAsc, 1)) < 0 Then ←And以下追加★
            'VB2005の場合で最後の1バイトが全角の半分の時
            Return strAsc.Substring(0, strAsc.Length - 1)
        Else
            Return strAsc
        End If

    End Function


確か、s_jisの2バイト文字は、後半の1バイトが必ずマイナスになる・・・という情報があったような???と思い、★を追加。
ひらがな、漢字、カタカナ(1バイト除く)、全角記号・・。大丈夫かな・・・