2009年2月18日水曜日

.NET パラメータクエリーを使用しOracleのDateTime型フィールドにDbNullをInsertまたはUpdateすると「リテラル文字が一致しません」と失敗する場合がある。

パラメータクエリーを使用しOracleのDateTime型フィールドにDbNullをInsertまたはUpdateすると「リテラル文字が一致しません」と失敗する場合があります。

なぜだろうとググってみると・・・自分のブログがヒットした・・・
OracleのフィールドにDbNull.Valueを登録する際の注意

かなりの時間を無駄にした(ヽ´ω`)ゲッソリ

2009年2月13日金曜日

正規表現 サンプル

半角数字のみ
[0-9]

半角英字のみ
[a-zA-Z]

半角英数のみ
[a-zA-Z0-9]

半角英数記号のみ
[!-~]

.NET 定数ファイルを作成する~その2~

今回はWeekDayクラス、WeekDayHasNoneクラス、WeekDayHasNotSunクラスに
インスタンス化せずにCDから名前を検索できるメソッドを追加します。

前回、作成したコードをまとめるとこんな感じです。
NameSpace Constant
Public Class ConstItem
Private _Cd As Integer
Private _Name As String
Private _AliasName As String

Private Sub New
End Sub 

Public Sub New(cd As Integer, name As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = String.Empty
End Sub

Public Sub New(cd As Integer, name As String, aliasName As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = aliasName
End Sub

Public ReadOnly Property Cd() As Integer
Get
Return Me._Cd
End Get
End Property

Public ReadOnly Property Name() As String
Get
Return Me._Name
End Get
End Property

Public ReadOnly Property AliasName() As String
Get
Return Me._AliasName
End Get
End Property

End Class
End NameSpace


NameSpace Constant
Public Class WeekDay
Public Shared ReadOnly SUN As New ConstItem(1, "日曜日","日")
Public Shared ReadOnly MON As New ConstItem(2, "月曜日","月")
Public Shared ReadOnly TUE As New ConstItem(3, "火曜日","火")
Public Shared ReadOnly WED As New ConstItem(4, "水曜日","水")
Public Shared ReadOnly THR As New ConstItem(5, "木曜日","木")
Public Shared ReadOnly FRI As New ConstItem(6, "金曜日","金")
Public Shared ReadOnly SAT As New ConstItem(7, "土曜日","土")

Public Shared Function CreateList As List(Of ConstItem)
Dim list As New List(Of ConstItem)
list.Add(SUN)
list.Add(MON)
list.Add(TUE)
list.Add(WED)
list.Add(THR)
list.Add(FRI)
list.Add(SAT)
Return list
End Function
End Class

Public Class WeekDayHasNone
Inherits WeekDay

Public Shared ReadOnly NONE As New ConstItem(0, "なし")

Public Shared Shadows Function CreateList As List(Of ConstItem)
Dim list As List(Of ConstItem)
list = WeekDay.CreateList
list.InsertAt(0,NONE)
Return list
End Function
End Class

Public Class WeekDayHasNotSun
Inherits WeekDay

Private Shared Shadows ReadOnly SUN As New ConstItem(1, "日曜日","日")

Public Shared Shadows Function CreateList As List(Of ConstItem)
Dim list As List(Of ConstItem)
list = WeekDay.CreateList
list.RemoveAt(WeekDay.SUN)
Return list
End Function
End Class
End NameSpace



簡単に思いついたのは各クラスに下記のようなコードを追加していくことでした。
Public Shared Function Find(ByVal cd As Integer) As ConstItem
Dim item As ConstItem = Nothing
Dim list As List(Of ConstItem) = 各クラス名.CreateList
       For idx As Integer = 0 To list.Count - 1
             If list.Item(idx).Cd = cd Then
item = list.Item(idx)
Continue For
End If
Next
Return item
End Function

・・・これじゃぁダメだよね(;´∀`)


次に思いついたのはList<Of T>のFindメソッドで探すことです。
Findメソッドの使い方は以下のようなコードになります。
これが結構面倒なんですよね。
Public Class Test

Private _SearchCd As Integer

Public Sub Test()
Dim list As New List(Of KeyValuePair(Of Integer, String))
list.Add(New KeyValuePair(Of Integer, String)(1, "日曜日"))
list.Add(New KeyValuePair(Of Integer, String)(2, "月曜日"))
list.Add(New KeyValuePair(Of Integer, String)(3, "火曜日"))

'CD=2を検索
Me._SearchCd = 2
Dim findItem As KeyValuePair(Of Integer, String) = list.Find(AddressOf IsMatch)
If IsNothing(findItem) Then
Console.WriteLine("該当データなし")
Else
Console.WriteLine("Key:{0},Value:{1},", findItem.Key, findItem.Value)
End If

End Sub

Private Function IsMatch(ByVal item As KeyValuePair(Of Integer, String)) As Boolean
Return item.Key = Me._SearchCd
End Function
End Class




そこでList(Of T)を継承したConstListクラスを作成し、Find(Cd)メソッドを追加します。
ついでに名前から検索するFind(Name)も作っておきます。
Namespace Constant
  ''' <summary>
''' 定数アイテムのリストを管理するクラスです。
''' </summary>
''' <remarks></remarks>
Public Class ConstList
Inherits List(Of ConstItem)

''' <summary>
''' CDに該当する最初のConstItemを取得します。
''' </summary>
''' <param name="cd"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Overloads Function Find(ByVal cd As Integer) As ConstItem
Dim filter As New ConstItemFilter(Of Integer)
filter.FilterValue = cd
Return Me.Find(AddressOf filter.IsMatchCd)
End Function

''' <summary>
''' Nameに該当する最初のConstItemを取得します。
''' </summary>
''' <param name="name"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Overloads Function Find(ByVal name As String) As ConstItem
Dim filter As New ConstItemFilter(Of String)
filter.FilterValue = name
Return Me.Find(AddressOf filter.IsMatchName)
End Function

End Class

End Namespace


Findメソッドで実際に検索するFilterクラスを作成します。
Namespace Constant
  ''' <summary>
  ''' 定数リストより定数アイテムを検索するためのFilterクラスです。
  ''' </summary>
''' <remarks></remarks>
Public Class ConstItemFilter(Of TValue)

    ''' <summary>検索する値です</summary>
Private _FilterValue As TValue

    ''' <summary>デフォルトコンストラクタ</summary>
Public Sub New()
End Sub

    ''' <summary>コンストラクタ</summary>
    ''' <param name="filterValue">検索する値</param>
Public Sub New(ByVal filterValue As TValue)
Me.New()
Me._FilterValue = filterValue
End Sub

    ''' <summary>検索する値を取得および設定します。</summary>
Public Property FilterValue() As TValue
Get
Return _FilterValue
End Get
Set(ByVal value As TValue)
_FilterValue = value
End Set
End Property
    
    ''' <summary>引数に指定した定数アイテムのCDと検索値が一致するかを取得します。</summary>
    ''' <param name="item">定数アイテム</param>
    ''' <returns>一致する場合はTrue。それ以外はFalse。</returns>
Public Function IsMatchCd(ByVal item As ConstItem) As Boolean
If (Me._FilterValue Is Nothing) Then Return False
Return (Me._FilterValue.Equals(item.Cd))
End Function

    ''' <summary>引数に指定した定数アイテムのNameと検索値が一致するかを取得します。</summary>
    ''' <returns>一致する場合はTrue。それ以外はFalse。</returns>
Public Function IsMatchName(ByVal item As ConstItem) As Boolean
If (Me._FilterValue Is Nothing) Then Return False
Return (Me._FilterValue.Equals(item.Name))
End Function
End Class
End Namespace


ConstItemクラスの修正はありません。
Namespace Constant
  ''' <summary>
  ''' 定数アイテムクラスです。
  ''' </summary>
''' <remarks></remarks>   
Public Class ConstItem
    ''' <summary>コードです</summary>
Private _Cd As Integer
    ''' <summary>名前です</summary>
Private _Name As String
    ''' <summary>別名です</summary>
Private _AliasName As String
    
    ''' <summary>デフォルトコンストラクタ</summary>
Private Sub New()
End Sub
    
    ''' <summary>コンストラクタ</summary>
    ''' <param name="cd">コード</param>
    ''' <param name="name">名前</param>
Public Sub New(ByVal cd As Integer, ByVal name As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = String.Empty
End Sub

    ''' <summary>コンストラクタ</summary>
    ''' <param name="cd">コード</param>
    ''' <param name="name">名前</param>
    ''' <param name="aliasName">別名</param>
Public Sub New(ByVal cd As Integer, ByVal name As String, ByVal aliasName As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = aliasName
End Sub
  
    ''' <summary>コードを取得します。</summary>
Public ReadOnly Property Cd() As Integer
Get
Return Me._Cd
End Get
End Property

    ''' <summary>名前を取得します。</summary>
Public ReadOnly Property Name() As String
Get
Return Me._Name
End Get
End Property

    ''' <summary>別名を取得します。</summary>
Public ReadOnly Property AliasName() As String
Get
Return Me._AliasName
End Get
End Property
End Class

End Namespace

定数ファイルのCreateListメソッドを修正し、ConstListクラスを返すようにします。
Namespace Constant
  ''' <summary>
  ''' 曜日リストです。
  ''' </summary>
''' <remarks></remarks>  
Public Class WeekDay
Public Shared ReadOnly SUN As New ConstItem(1, "日曜日", "日")
Public Shared ReadOnly MON As New ConstItem(2, "月曜日", "月")
Public Shared ReadOnly TUE As New ConstItem(3, "火曜日", "火")
Public Shared ReadOnly WED As New ConstItem(4, "水曜日", "水")
Public Shared ReadOnly THR As New ConstItem(5, "木曜日", "木")
Public Shared ReadOnly FRI As New ConstItem(6, "金曜日", "金")
Public Shared ReadOnly SAT As New ConstItem(7, "土曜日", "土")

Public Shared Function CreateList() As ConstList
Dim list As New ConstList
list.Add(SUN)
list.Add(MON)
list.Add(TUE)
list.Add(WED)
list.Add(THR)
list.Add(FRI)
list.Add(SAT)
Return list
End Function

End Class

  ''' <summary>
  ''' なしを保有する曜日リストです。
  ''' </summary>
''' <remarks></remarks>   
Public Class WeekDayHasNone
Inherits WeekDay

Public Shared ReadOnly NONE As New ConstItem(0, "なし")

Public Shared Shadows Function CreateList() As ConstList
Dim list As ConstList
list = WeekDay.CreateList
list.Insert(0, NONE)
Return list
End Function

End Class

  ''' <summary>
  ''' 日曜日を保有しない曜日リストです。
  ''' </summary>
''' <remarks></remarks>     
Public Class WeekDayHasNotSun
Inherits WeekDay

Private Shared Shadows ReadOnly SUN As New ConstItem(1, "日曜日", "日")

Public Shared Shadows Function CreateList() As ConstList
Dim list As ConstList
list = WeekDay.CreateList
list.Remove(WeekDay.SUN)
Return list
End Function


End Class
End Namespace


使い方
'名前を取得します。
Console.WriteLine(Constant.WeekDay.SUN.Name)
'別名を取得します。
Console.WriteLine(Constant.WeekDay.SUN.AliasName)

'コンボボックスに設定します。
ComboBox1.ValueMember = "Cd"
ComboBox1.DisplayMember = "Name"
'別名の場合
'ComboBox1.DisplayMember = "AliasName"
ComboBox1.DataSource = Constant.WeekDay.CreateList

'CD=1に該当する定数アイテムを取得します。
Dim findCd As Integer = 1
Dim findItem As ConstItem = WeekDay.CreateList.Find(findCd)
If IsNothing(findItem) Then
Console.WriteLine("Cd={0}に該当するアイテムはありません。",findCd)
Else
Console.WriteLine("Cd:{0},Name:{1},Name:{2}",findItem.Cd, findItem.Name, findItem.AliasName")
End If

'Name="木曜日"に該当する定数アイテムを取得します。
Dim findName As String = "木曜日"
Dim findItem As ConstItem = WeekDay.CreateList.Find(findName)
If IsNothing(findItem) Then
Console.WriteLine("Name={0}に該当するアイテムはありません。",findName)
Else
Console.WriteLine("Cd:{0},Name:{1},Name:{2}",findItem.Cd, findItem.Name, findItem.AliasName")
End If




難点はCdから定数アイテムを検索する際にCreateList経由でしかできない事です。
一応これで要件はすべて満たしたのでOKとします。

.NET 定数ファイルを作成する~その1~

定数ファイル「Constant」に「曜日」に関する定数を作ったとします。
こんな感じでしょうか。
Public Class Constant
Public Const SUN As Integer = 1
Public Const MON As Integer = 2
Public Const TUE As Integer = 3
Public Const WED As Integer = 4
Public Const THR As Integer = 5
Public Const FRI As Integer = 6
Public Const SAT As Integer = 7
End Class

この定数ファイル「Constant」にどんどん定数を作っていくと、
Constantoのインテリセンスから定数を探すのが大変です。


そこでグループ化したいと考えて、簡単に列挙体にしました。
Public Class Constant
Public Enum WeekDay
SUN = 1
MON = 2
TUE = 3
WED = 4
THR = 5
FRI = 6
SAT = 7
End Enum
End Class



よくある事ですが
SUNを指定したとき「1」を取得したい場合と「日曜日」を取得したい場合があると思います。
そこで列挙体をクラスに変え、KeyValuePairで値と名前をセットで宣言するようにしました。
使うときはConstant.WeekDay.SUN.Keyで「1」を取得し、Constant.WeekDay.SUN.Valueで「日曜日」を取得します。
Namespace Constant
Public Class WeekDay
Public Shared ReadOnly SUN As New KeyValuePair(Of Integer, String)(1, "日曜日")
Public Shared ReadOnly MON As New KeyValuePair(Of Integer, String)(2, "月曜日")
Public Shared ReadOnly TUE As New KeyValuePair(Of Integer, String)(3, "火曜日")
Public Shared ReadOnly WED As New KeyValuePair(Of Integer, String)(4, "水曜日")
Public Shared ReadOnly THR As New KeyValuePair(Of Integer, String)(5, "木曜日")
Public Shared ReadOnly FRI As New KeyValuePair(Of Integer, String)(6, "金曜日")
Public Shared ReadOnly SAT As New KeyValuePair(Of Integer, String)(7, "土曜日")
End Class
End Namespace



ところが
SUNを指定したとき「日曜日」とは別に「日」を取得したい場合が出てきました。
そこで値「1」と名前「日曜日」と別名「日」をセットで管理するクラスを作成します。
これで「Sunday」や「Sun」など別名がふえても、プロパティを追加すれば大丈夫です。
NameSpace Constant
Public Class ConstItem
Private _Cd As Integer
Private _Name As String
Private _AliasName As String

Private Sub New
End Sub 

Public Sub New(cd As Integer, name As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = String.Empty
End Sub

Public Sub New(cd As Integer, name As String, aliasName As String)
Me._Cd = cd
Me._Name = name
Me._AliasName = aliasName
End Sub

Public ReadOnly Property Cd() As Integer
Get
Return Me._Cd
End Get
End Property

Public ReadOnly Property Name() As String
Get
Return Me._Name
End Get
End Property

Public ReadOnly Property AliasName() As String
Get
Return Me._AliasName
End Get
End Property

End Class
End NameSpace


NameSpace Constant
Public Class WeekDay
Public Shared ReadOnly SUN As New ConstItem(1, "日曜日","日")
Public Shared ReadOnly MON As New ConstItem(2, "月曜日","月")
Public Shared ReadOnly TUE As New ConstItem(3, "火曜日","火")
Public Shared ReadOnly WED As New ConstItem(4, "水曜日","水")
Public Shared ReadOnly THR As New ConstItem(5, "木曜日","木")
Public Shared ReadOnly FRI As New ConstItem(6, "金曜日","金")
Public Shared ReadOnly SAT As New ConstItem(7, "土曜日","土")
End Class
End NameSpace

使うときはConstant.WeekDay.SUN.Cdで「1」を取得し、Constant.WeekDay.SUN.Nameで「日曜日」を取得し、Constant.WeekDay.SUN.AliasNameで「日」を取得します。


今度はこの定数をコンボボックスのリストアイテムにセットしたい場面が出てきました。
その都度リストを作るのが面倒とのことで、WeekDayクラスにリストを作るメソッドを用意します。
※インスタンス化せずに使える事が前提です。
NameSpace Constant
Public Class WeekDay
Public Shared ReadOnly SUN As New ConstItem(1, "日曜日","日")
Public Shared ReadOnly MON As New ConstItem(2, "月曜日","月")
Public Shared ReadOnly TUE As New ConstItem(3, "火曜日","火")
Public Shared ReadOnly WED As New ConstItem(4, "水曜日","水")
Public Shared ReadOnly THR As New ConstItem(5, "木曜日","木")
Public Shared ReadOnly FRI As New ConstItem(6, "金曜日","金")
Public Shared ReadOnly SAT As New ConstItem(7, "土曜日","土")

Public Shared Function CreateList As List(Of ConstItem)
Dim list As New List(Of ConstItem)
list.Add(SUN)
list.Add(MON)
list.Add(TUE)
list.Add(WED)
list.Add(THR)
list.Add(FRI)
list.Add(SAT)
Return list
End Function
End Class
End NameSpace

コンボボックスにWeekDayリスト設定するときは以下のようにします。
ComboBox1.ValueMember = "Cd"
ComboBox1.DisplayMember = "Name"
’別名の場合
'ComboBox1.DisplayMember = "AliasName"
ComboBox1.DataSource = Constant.WeekDay.CreateList


ところがWeekDayクラスにNone[0]を追加してほしい。しかしNone[0]がないWeekDayもそのまま使いたいとの要望がありました。
仕方がないのでWeekDayクラスを継承してWeekDayHasNoneクラスを作成しました。
NameSpace Constant
Public Class WeekDayHasNone
Inherits WeekDay

Public Shared ReadOnly NONE As New ConstItem(0, "なし")

Public Shared Shadows Function CreateList As List(Of ConstItem)
Dim list As List(Of ConstItem)
list = WeekDay.CreateList
list.InsertAt(0,NONE)
Return list
End Function
End Class
End NameSpace



さらにWeekDayクラスからSUN[1]を削除したものが欲しい。しかしSUN[1]があるWeekDayもそのまま使いたいとの要望がありました。
WeekDayクラスを継承してWeekDayHasNotSunクラスを作成しました。
NameSpace Constant
Public Class WeekDayHasNotSun
Inherits WeekDay

Private Shared Shadows ReadOnly SUN As New ConstItem(1, "日曜日","日")

Public Shared Shadows Function CreateList As List(Of ConstItem)
Dim list As List(Of ConstItem)
list = WeekDay.CreateList
list.RemoveAt(WeekDay.SUN)
Return list
End Function
End Class
End NameSpace




CDから名前を検索できるメソッドがあればいいよね(もちろんインスタンス化せずに)との要望。←今ココ
・・・どうするかなぁ