3

基本的に、データを取得するための3つのデータベースがあります。1つはSQLServerデータベース、もう1つはAccessデータベース(ネットワークドライブなどをマップする必要があるため、接続するのが特に面倒です)、最後の1つはITが最終的に権利を付与したときにOracleデータベースになります。

これらのデータベースのいずれかをできるだけ簡単にクエリできるヘルパー関数を作成することを考えています。理想的には、2次元配列を作成したい

Dim myEasyResultArray(10,10) as String
myEasyResultArray = DatabaseHelper("Access", "SELECT * FROM Employee")

これは良い設計上の決定ですか?また、配列を適切なサイズにするにはどうすればよいですか?私はこれをすることができますか?

Dim myEasyResultArray = DatabaseHelper("Access", "SELECT * FROM Employee")

これはモジュールですか、それともクラスですか?変数を共有する必要はありませんが、

4

2 に答える 2

4

すべてのデータアクセスロジックをデータアクセス層に配置しようとします。理想的には、これは別のライブラリと名前空間にありますが、そうである必要はありません。私はクラスを使用します。通常はテーブル/エンティティごとに1つで、すべてのクラスがステートレスになるように設計します(したがって、データアクセスオブジェクトの同じインスタンスを再利用する必要はなく、必要なときにいつでも新しいインスタンスをインスタンス化できます。 DBにアクセスします)。

配列を返す代わりに、データオブジェクト(DTOと呼ばれることが多い-データ転送オブジェクト)を返すようにします。可能であれば、パブリックプロパティのみを含み、メソッドを含まないDTOクラスを可能な限りクリーンに保ちます。各データアクセスクラスの複数のバージョンを作成できるように、データアクセスクラスはすべてインターフェイスを実装する必要があります。1つはアクセス用、もう1つはOracle用、もう1つはSQL用などです。次に、データベースにアクセスする必要がある場合は常に(できれば、ビジネスレイヤーのみで、UIレイヤーではなく)、適切なデータアクセスオブジェクトを「一般的な"インターフェイスタイプ(これにより、ファクトリクラスが正しい具体的なデータアクセスオブジェクトタイプをビジネスオブジェクトに挿入する必要があります)。

DTOの実際の簡単な例を次に示します。

Public Class Employee
    Public Id As Guid
    Public Name As String
    Public StartDate As Date
End Class

これがデータアクセスインターフェースの例です

Public Interface IEmployeeDataAccess
    Function GetEmployee(id As Guid) As Employee
    Function GetEmployees() As List(Of Employee)
End Interface

データアクセスクラスの例を次に示します。

Public Class SqlEmployeeDataAccess
    Inherits IEmployeeDataAccess

    Public Function GetEmployee(id As Guid) As Employee Implements IEmployeeDataAccess.GetEmployee
        Dim employee As New Employee()
        ' Connect to SQL DB and populate employee DTO object
        Return employee
    End Function

    Public Function GetEmployees() As List(Of Employee) Implements IEmployeeDataAccess.GetEmployees
        Dim employees As New List(Of Employee)()
        ' Connect to SQL DB and populate list of employee DTO objects
        Return employees
    End Function
End Interface

次に、同様のクラスを呼び出しAccessEmployeeDataAccessOracleEmployeeDataAccess、IEmployeeDataAccessインターフェイスも実装する場合があります。次に、データアクセス層でも、サポートされているDBプロバイダーごとにファクトリクラスを作成します。次のように、すべてのDataAccessファクトリに同じインターフェイスを実装させます。

Public Interface IDataAccessFactory
    Function NewEmployeeDataAccess() As IEmployeeDataAccess
End Interface

Public Class SqlDataAccessFactory
    Implements IDataAccessFactory

    Public Function NewEmployeeDataAccess() As IEmployeeDataAccess
        Return New SqlEmployeeDataAccess()
    End Function
End Class

次に、私のビジネスクラスでは、次のようなことをするかもしれません。

Public Class EmployeeBusiness
    Public Sub New(employeeDataAccess As IEmployeeDataAcess)
        _employeeDataAccess = employeeDataAccess
    End Sub

    Private _employeeDataAccess As IEmployeeDataAcess

    Public Function GetEmployee(id As Guid) As Employee
        Return _employeeDataAccess.GetEmployee(id)
    End Function
End Class

そして、私のビジネスファクトリーでは、次のようなことをします。

Public Class BusinessFactory
    Public Sub New()
        Select Case dataAccessType
            Case "SQL"
                _dataAccessFactory = New SqlDataAccessFactory()
            Case "Oracle"
                _dataAccessFactory = New OracleDataAccessFactory()
            Case "Access"
                _dataAccessFactory = New AccessDataAccessFactory()
        End Select
    End Sub

    _dataAccessFactory As IDataAccessFactory

    Public Function NewEmployeeBusiness() As IEmployeeBusiness
        Return New EmployeeBusiness(_dataAccessFactory.NewEmployeeDataAccess())
    End Function
End Class

これは、任意のデータベースプロバイダーと連携する単一のデータアクセスオブジェクトセットを使用することで大幅に簡素化できます。これを行うには、SqlConnectionの代わりにIDbConnection、SqlCommandの代わりにIDbCommandなどの基本ADOタイプのみを使用する必要があります。次に、データアクセスオブジェクトは、DataAccessクラスが接続を必要とするときはいつでも、新しい接続などを作成できるDBプロバイダーファクトリを要求できます。ただし、これは、単にストアドプロシージャなどを呼び出す場合に、より簡単に実行できます。多くの場合、特にSQLセンテンスをコードで動的に構築する場合、プロバイダー間の違いが多すぎるため、すべてのDBプロバイダーに同じDataAccessクラスを使用することはできません。

しかし、それは私だけです...

于 2012-06-11T14:17:22.280 に答える
1

あなたの提案には大きな問題が1つあります。

1つ目は、プログラマーがこの形式に似たメソッドを使用してデータベースヘルプを構築したいと思うことがよくあることです。

DataTable GetData(string sql)

ここで重要な点は、メソッドがクエリパラメータを提供せずにSQL文字列を受け入れることです。これは間違っています。これはアンチパターンです。これは、クエリコードの一部としてSQLデータをエンコードすることを(ほとんど強制的に)奨励するためです。クエリパラメータを個別のデータとして正しく渡すためのメカニズムを提供する必要があります。配列は一般的ですが、それが唯一の方法ではありません。また、私は通常、文字列のみを受け入れるオーバーロードを提供しません。これは、必然的に悪用につながるためです。パラメータなしでクエリを送信する場合は、空の配列を渡します。このように、それがあなたの意図することであることは明らかであり、データベースヘルパーを使用する人は誰でも、パラメータを正しい方法で使用することを学ぶことが奨励されます。

他にも改善できることがありますが、これが主な問題です。

于 2012-06-11T14:30:27.577 に答える