2

今日はちょっと実験してみました。モデル エンティティとして型指定されていないデータ テーブルを使用するアプリケーションがあります。それらはすべて次のように作成されます。

Imports System.Data
Imports System.Runtime.Serialization
Imports System.ComponentModel

<DesignerCategory("Code"), system.Serializable()>
Partial Public Class SomeTable1
    Inherits DataTable

#Region
    Public Const TABLE_NAME As String = "SomeTable1"

    Public Const FIELD_SomeField1 As String = "SomeField1"
    Public Const FIELD_SomeField2 As String = "SomeField2"
#End Region

    Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
        MyBase.New(info, context)
    End Sub

    Public Sub New()
        MyBase.New()

        With Columns
            .Add(FIELD_SomeField1, GetType(System.String)).DefaultValue = String.Empty
            .Add(FIELD_SomeField2, GetType(System.Double)).DefaultValue = 0
        End With

        Dim keys(1) As DataColumn
        keys(0) = Columns(FIELD_SomeField1)
        TableName = TABLE_NAME
        PrimaryKey = keys
    End Sub
End Class

私は現在EFで作業しているので、私の混乱で、私はこのようなものを書きました(ええ、それはvbです):

Partial Public Class SomeTable1
    Inherits DataTable

    <Key()>
    Friend Property SomePK1 As DataColumn

    <Required(ErrorMessage:="SomeField1 is required.")>
    <DataType(DataType.Text)>
    Friend Property SomeField1 As DataColumn

    <Required()>
    <DataType(DataType.DateTime)>
    Friend Property SomeField2 As DataColumn
    ...

    Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
        MyBase.New(info, context)
    End Sub

    Public Sub New()
        MyBase.New()

        SomeField2 = Date.Now
    End Sub
End Class

以前の dt と同等のものを作成し、現在のデータ エンジンと完全に互換性を持つことを夢見ていました。

そして、型変換エラー (システム日付からデータ列へ) が私の希望を打ち砕きました。大変な週末だったことを認めざるを得ません:)

したがって、変更を完全に破棄する前に、上記のコードと同等ですが、いくつかの新しい機能を備えた型付きデータテーブルを作成する方法はありますか? これは非常に古いプログラミング方法で、ネット上で何も見つけることができません。前もって感謝します。

4

2 に答える 2

0

自分がやりたいことをする方法を見つけました。おそらくいくつかの作業が必要ですが、機能します。これが時代遅れの方法であることを知っているので、私のように古いプログラムを維持することを余儀なくされている他の人が恩恵を受けることができるように、そこに投稿しています。

型付きデータテーブルを実行するためのテンプレートは次のとおりです。

Imports System.Data
Imports System.ComponentModel
Imports System.Runtime.Serialization
Imports System.Diagnostics

'''<summary>
'''Represents the strongly named DataTable class.
'''</summary>
<Global.System.Serializable(), _
 Global.System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")> _
Partial Public Class tblMyTable
    Inherits TypedTableBase(Of tblMyTableRow)

    'Those are the StoredProcs names for (MANUAL) CRUD operations that the DBContext wrapper uses. (yuck! I hate thousands of them)
    'Public Const COMMAND_SAVE As String = "sp_MyTable_Save"
    'Public Const COMMAND_DELETE As String = "sp_MyTable_Delete"
    'Public Const COMMAND_LOADBY_ID As String = "sp_MyTable_LoadBy_Id"

    'Those are constants I maintain for untyped (but somewhat strong) compatibility
    Public Const FIELD_pID As String = "pID"
    Public Const FIELD_SomeOther As String = "SomeOtherField"

    'Basic CRUD, uses company data as the app hot swapps DBs (one for company)
    'Public Function Save(ByVal company As DataRow) As Short
    '    Return New Base(company).Update(Me, COMMAND_SAVE, COMMAND_DELETE)
    'End Function

    'Public Sub LoadByID(ByVal company As DataRow, Id As Integer)
    '    Me.Rows.Clear()
    '    Me.Merge(New Base(company).FillDataTable(Of tblMyTable)(COMMAND_LOADBY_ID, Id))
    'End Sub

    <DebuggerNonUserCodeAttribute()>
    Private Sub InitClass()
        Me.columnpID = New DataColumn(FIELD_pID, GetType(Integer), Nothing, MappingType.Element) With
                   {.AllowDBNull = False, .ReadOnly = True, .Unique = True,
                    .AutoIncrement = True, .AutoIncrementSeed = -1, .AutoIncrementStep = -1}
        MyBase.Columns.Add(Me.columnpID)
        Me.columnSomeOtherField = New DataColumn(FIELD_SomeOther, GetType(String), Nothing, MappingType.Element) With
                           {.MaxLength = 5, .AllowDBNull = False, .DefaultValue = String.Empty}
        MyBase.Columns.Add(Me.columnSomeOtherField)
    End Sub

    Private columnpID As DataColumn
    Private columnSomeOtherField As DataColumn

    <DebuggerNonUserCodeAttribute()>
    Public Sub New()
        MyBase.New()
        Me.TableName = "tblMyTable"
        Me.BeginInit()
        Me.InitClass()
        Me.EndInit()
    End Sub

    <DebuggerNonUserCodeAttribute()>
    Friend Sub New(ByVal table As DataTable)
        MyBase.New()
        Me.TableName = table.TableName
        If (table.CaseSensitive <> table.DataSet.CaseSensitive) Then
            Me.CaseSensitive = table.CaseSensitive
        End If
        If (table.Locale.ToString <> table.DataSet.Locale.ToString) Then
            Me.Locale = table.Locale
        End If
        If (table.Namespace <> table.DataSet.Namespace) Then
            Me.Namespace = table.Namespace
        End If
        Me.Prefix = table.Prefix
        Me.MinimumCapacity = table.MinimumCapacity
    End Sub

    <DebuggerNonUserCodeAttribute()>
    Protected Sub New(ByVal info As Global.System.Runtime.Serialization.SerializationInfo, ByVal context As Global.System.Runtime.Serialization.StreamingContext)
        MyBase.New(info, context)
        Me.InitVars()
    End Sub

    <DebuggerNonUserCodeAttribute()>
    Public ReadOnly Property pIDColumn() As DataColumn
        Get
            Return Me.columnpID
        End Get
    End Property

    <DebuggerNonUserCodeAttribute()>
    Public ReadOnly Property SomeOtherFieldColumn() As DataColumn
        Get
            Return Me.columnSomeOtherField
        End Get
    End Property

    <DebuggerNonUserCodeAttribute(), Browsable(False)>
    Public ReadOnly Property Count() As Integer
        Get
            Return Me.Rows.Count
        End Get
    End Property

    <DebuggerNonUserCodeAttribute()>
    Default Public ReadOnly Property Item(ByVal index As Integer) As tblMyTableRow
        Get
            Return CType(Me.Rows(index), tblMyTableRow)
        End Get
    End Property

    <DebuggerNonUserCodeAttribute()>
    Public Overrides Function Clone() As DataTable
        Dim cln As tblMyTable = CType(MyBase.Clone, tblMyTable)
        cln.InitVars()
        Return cln
    End Function

    <DebuggerNonUserCodeAttribute()>
    Protected Overrides Function CreateInstance() As DataTable
        Return New tblMyTable()
    End Function

    <DebuggerNonUserCodeAttribute()>
    Friend Sub InitVars()
        Me.columnpID = MyBase.Columns(FIELD_pID)
        Me.columnSomeOtherField = MyBase.Columns(FIELD_SomeOther)
    End Sub

    <DebuggerNonUserCodeAttribute()>
    Public Function NewtblMyTableRow() As tblMyTableRow
        Return CType(Me.NewRow, tblMyTableRow)
    End Function

    <DebuggerNonUserCodeAttribute()>
    Protected Overrides Function NewRowFromBuilder(ByVal builder As DataRowBuilder) As DataRow
        Return New tblMyTableRow(builder)
    End Function

    <DebuggerNonUserCodeAttribute()>
    Protected Overrides Function GetRowType() As Global.System.Type
        Return GetType(tblMyTableRow)
    End Function

    <DebuggerNonUserCodeAttribute()>
    Public Sub RemovetblMyTableRow(ByVal row As tblMyTableRow)
        Me.Rows.Remove(row)
    End Sub

End Class

'''<summary>
'''Represents strongly named DataRow class.
'''</summary>
Partial Public Class tblMyTableRow
    Inherits DataRow

    Private tabletblMyTable As tblMyTable

    <DebuggerNonUserCodeAttribute()>
    Friend Sub New(ByVal rb As DataRowBuilder)
        MyBase.New(rb)
        Me.tabletblMyTable = CType(Me.Table, tblMyTable)
    End Sub

    <DebuggerNonUserCodeAttribute()>
    Public Property pID() As Integer
        Get
            Return CType(Me(Me.tabletblMyTable.pIDColumn), Integer)
        End Get
        Set(value As Integer)
            Me(Me.tabletblMyTable.pIDColumn) = value
        End Set
    End Property

    <DebuggerNonUserCodeAttribute()>
    Public Property SomeOtherField() As String
        Get
            Return CType(Me(Me.tabletblMyTable.SomeOtherFieldColumn), String)
        End Get
        Set(value As String)
            Me(Me.tabletblMyTable.SomeOtherFieldColumn) = value
        End Set
    End Property
End Class

必要なのはそれだけです。おそらくそれを減らすことができますが、そうするとデータセット関数が期待どおりに機能しなくなります。

ID(VS2010)によって自動的に生成されたコードが必要な場合は、次の手順に従う必要があります。

  1. サーバー エクスプローラーで、お気に入りの DB への接続を作成します。
  2. プロジェクトの上で右クリックし、新しい要素の追加を選択します。
  3. データセット オブジェクト テンプレートを選択するだけです。名前は関係ありません。デザイナー ビューで開きます。
  4. データベースからテーブルを選択し、データセット デザイナーにドラッグします。
  5. 次に...上部のクラスセレクターを見てください。
  6. [yourTableName]Datatable を展開して見つけます。クリックして。
  7. DataSet1.designer.vb (cs) ファイル内の当該クラスにジャンプします。
  8. 次のクラスは行定義です。それらをコピーして新しいクラスファイルに貼り付けるだけです。
  9. より完全なデータ テーブル オブジェクトが必要な場合は、行クラスの下の次のクラスでイベントを定義し、デリゲートはテーブル定義のすぐ上にあります。

シンプルで、untyped を使用する残りのプログラムと組み合わせて動作することをテストしました。うんちを磨くようなものかもしれませんが、EF のようにクライアントの検証を行うために、どこかにデータ注釈を追加したいと考えています。そして、おそらくそれらの列コンストラクターパラメーターを置き換えます。(しかし、私はできません)

幸運を。

于 2013-03-07T17:28:03.743 に答える
0

完全にフォローしているかどうかはわかりませんが、FIELD_SomeField2 を double として定義しているようです

(最初のスニペットのこの行)

.Add(FIELD_SomeField2, GetType(System.Double)).DefaultValue = 0

しかし、2 番目のスニペットで SomeField2 を DateTime として定義していることがわかります。

<Required()>
<DataType(DataType.DateTime)>
Friend Property SomeField2 As DataColumn

だから多分ただのタイプの不一致...

于 2013-03-05T17:58:05.850 に答える