web-dev-qa-db-ja.com

リポジトリパターンとデータベースクエリ

他の投稿を読んだとき、「リポジトリ」と「データベース」の概念は完全に別の概念であることを意図しているため、うまく調和していないように見えますが、とにかく質問します。

私は現在、たまたますべてが異なるいくつかのデータベース(Oracle、sybase、sqlサーバー)からさまざまなタイプのデータ(1つのタイプのデータは数千のレコードで構成される場合があります)をインポートし、そのデータを処理する必要があります(データセットの種類に応じて) is)、その処理済みデータを別のデータベースに書き込みます。現在使用している言語はC#です。

私の状況でリポジトリパターンを使用すると便利な場合があると言われましたが、どのように設計するか、さらに重要なことに、このコンテキストですべての異なるパラメーター化されたSQLクエリをどこに配置するかわかりません。非常に多くのさまざまな製品とさまざまなデータベースソースがあることは、混乱を助長するだけです。

最初の段落で述べた理由により、私のリポジトリは実際には上の層にありますが、SQLクエリはデータアクセス層の一部である必要があると感じています。私はこのすべてを間違っているのですか?リポジトリパターンは実際に私の問題を解決するひどい方法ですか?

7
Iliana

私の2セント:データベースはデータベースです。リポジトリは、データベースの概念を抽象化するものです。

データベースと言うときは、MS SQL Server、Oracle、DB2、MySQL、PostgreSQLのようないくつかのキーワードが直接頭に浮かびます。

しかし、概念を少し拡張すると、データベースは、通常は構造化された方法でレコードを配置できる場所であり、これらのレコードに対してクエリを実行します。

この意味で、データベースはファイルシステム内のディレクトリであり、一連のテキストファイルが分散していて、各テキストファイルは複数の行で構成されており、各行はたとえば1つのレコードを表しています。

とはいえ、リポジトリとは何ですか?リポジトリは、データベースよりも上位の抽象化レベルです。魔法のような場所からオブジェクトを保存、取得、クエリする場所で、アプリケーションが完全に認識していない場合があります。

具体例:車、交通チケット、人の3つの異なるタイプのレコードがあるとします。これらは、次のスキーマで相互に関連しています。

  • 人は車を持たないか、多くの車を持っています。
  • 車の交通チケットはゼロまたは多数です。

また、これらには次の属性があります。

  • 個人{名前、SSN} = SSNは一意の識別子です。
  • 車{OwnerSSN、LicensePlate} =ライセンスプレートは一意の識別子です。
  • TrafficTicket {Id、LicensePlate、Severity、Points、Value} = Idは一意の識別子です。

これまでのところ、いいですね?

ここで、どこかからダウンロードできるテキストファイルとして提供される、交通チケットの巨大なデータベースがあると想像してください。明らかに違法なものはありません。

また、社内にOracleデータベースがあり、個人のリスト(それぞれが会社の従業員)のリストがあります。

また、MySQLデータベースへの直接アクセスを許可したパートナーから照会できる車のリストがあります。

あなたのマネージャー、ナイスガイ-怪しげな倫理的背景を持っている-は、彼の雇用主のうち何人が悪い運転記録を持っているかについての報告を彼に報告するように頼みます。彼はそれを使用して会社の駐車場の駐車スペースを活用したいと考えており、このレポートを提供するよう脅迫していますOR ELSE ...

プロットは濃くなります。レポートを作成する時間がほとんどありません。あなたの家の請求書は期日を迎えており、あなたは家族を養う必要があります(小さなベンが朝のシリアルなしで何をするでしょうか?)そこで、あなたは怪しげなマネージャーに対処し、後で彼をFBIに報告することにしました。結局のところ、あちこちに技術的な課題があるのは素晴らしいことです。

あなたは賢くてクールで、LINQ-fuを知っているので、C#プロジェクトを作成することにしました。また、プロジェクトを次のように構成します。

名前空間:

ShadyReport.TextFiles.DAL
    TrafficTicketReader.cs
        public List<TrafficTicket> GetAllTrafficTicketsFromTextFile(string pathOfCompletelyLegalTextFile)

ShadyReport.Oracle.DAL
    EF6OracleContext.cs    *(your Entity Framework Oracle DB Context)*

ShadyReport.MySQL.DAL
    EF6MySQLContext.cs     *(your Entity Framework MySQL DB Context)*

ShadyReport.Repository
    PersonRepository.cs
        public List<Person> GetAllPersons()

    CarRepository.cs
        public List<Car> GetCarsOfPersons(List<Person> persons)

    TrafficTicketRepository.cs
        public List<TrafficTicket> GetTrafficTicketsOfCars(List<Car> cars)

ShadyReport.Entity
    TrafficTicket.cs *(simple POCO object)*
    Person.cs        *(simple POCO object)*
    Car.cs           *(simple POCO object)*

ShadyReport.Business
    ShadyReportGenerator.cs
        public void GenerateShadyReport()

ここでは、Entity Frameworkの操作方法を知っており、DBContextが異なると、それぞれが異なるデータベースを指す異なるConnectionStringを持つ可能性があることを理解していると想定しています。

とはいえ、これはGenerateShadyReport()メソッドが次のようになる方法です。

public void GenerateShadyReport()
{
    var personRepository = new ShadyReport.Repository.PersonRepository();
    var carRepository = new ShadyReport.Repository.CarRepository();
    var ticketRepository = new ShadyReport.Repository.TrafficTicketRepository();

    var persons = personRepository.GetAllPersons();
    var cars = carRepository.GetCarsOfPersons(persons);
    var tickets = ticketRepository.GetTrafficTicketsOfCars(cars);

    var shadyReport = <LINQ magic stuff to tie the objects above together>
}

ご覧のとおり、レポートジェネレーターは、データがどこから来たのかを知りません。レポートジェネレータの観点から見ると、データベースはリポジトリからデータをフェッチするため、存在しない概念です。

そうは言っても、特定のパラメーター化されたクエリは特定のリポジトリに配置する必要があります。人ごとに車をフィルターするクエリはCarsリポジトリにある必要があります。一方、さまざまなソースからのものを結び付けるクエリは、リポジトリの上のビジネスレイヤーで行われます。これは彼らがどのように見えるかです:

+-----------------+---+
| UI              | E |
+-----------------+ n |
| Business        | t |
+-----------------+ i |
| Repository      | t |
+-----------------+ y |
| DAL             |   |
+-----------------+---+

そして、コールグラフは常に1つの方法です:ダウン。 UIは、DALを呼び出すリポジトリを呼び出すBusinessを呼び出します。そして、それらはすべて「話す」実体です。

これがお役に立てば幸いです。リポジトリについての決定的な答えではありませんが、このような答えは通常、概念を理解するのに役立ちます。

5
Machado