検索
ホームページバックエンド開発C++ORM を含むリポジトリを使用したコード内でのデータ アクセス

Data access in code, using repositories, even with ORMs

イントロ

.NET の世界では、データベースにアクセスする最もよく使用される方法の 1 つは、言語構文と緊密に統合されたオブジェクト リレーショナル マッパー (ORM) である Entity Framework (EF) を使用することです。 .NET 言語にネイティブな統合言語クエリ (LINQ) を使用すると、SQL の知識がなくても、通常の .NET コレクションを操作するような感覚でデータ アクセスを行うことができます。これには長所と短所がありますが、ここではそれについて暴言を吐かないようにします。しかし、それが常に引き起こす問題の 1 つは、ソフトウェア プロジェクトの構造、抽象化のレベル、そして最終的には単体テストに関する混乱です。

この投稿では、リポジトリの抽象化が常に役立つ理由を説明します。多くの人が抽象化されたデータ アクセスの用語としてリポジトリを使用していますが、同様のものに関連するリポジトリ ソフトウェア パターンもありますが、同じものではないことに注意してください。ここでは、データ アクセスの実装詳細を抽象化した一連のインターフェイスをリポジトリと呼び、設計パターンを完全に無視します。

歴史

ご存知の方は読み飛ばしていただいても構いませんが、そもそもリポジトリという考え方に至った経緯についてお話ししておかなければなりません。

先史時代のコードは、構造も何もなく、やりたいこと、または少なくとも望んでいることを実行するために、そのまま書かれていました。自動テストはなく、手動でハッキングして機能するまでテストするだけでした。各アプリケーションは、コード構造、再利用、読みやすさよりも重要なハードウェア要件を考慮して、手元にあるもので書かれました。それが恐竜を殺したのです!本当の事実。

ゆっくりとパターンが現れ始めました。特にビジネス アプリケーションの場合、ビジネス コード、データの永続性、およびユーザー インターフェイスが明確に分離されました。これらはレイヤーと呼ばれ、すぐに異なるプロジェクトに分割されました。これは、異なる懸念事項をカバーするだけでなく、レイヤーを構築するために必要なスキルが特に異なるためでもありました。 UI デザインはコード ロジックの作業とは大きく異なり、SQL やデータを永続化するために使用される言語やシステムとも大きく異なります。

したがって、ビジネスとデータ層の間の対話は、インターフェースとモデルに抽象化することによって行われました。ビジネス クラスとして、テーブル内のエントリのリストを要求するのではなく、フィルター処理された複雑なオブジェクトのリストが必要になります。永続化されたものにアクセスし、それをビジネスにとって理解可能なものにマッピングするのはデータ層の責任です。これらの抽象化はリポジトリと呼ばれるようになりました。

データ アクセスの下位レイヤーでは、CRUD のようなパターンがすぐに引き継がれました。テーブルのような構造化永続コンテナーを定義し、レコードを作成、読み取り、更新、削除します。コードでは、この種のロジックはリスト、辞書、配列などのコレクションに抽象化されます。そのため、リポジトリはコレクションのように動作するべきであり、実際の作成、読み取り、更新、削除以外のメソッドを持たないほど汎用的なものにするべきであるという意見の流れもありました。

しかし、私は強く反対します。ビジネスからのデータ アクセスを抽象化したものであるため、データ アクセスのパターンから可能な限り遠ざけ、ビジネス要件に基づいてモデル化する必要があります。ここで、特に Entity Framework だけでなく、他の多くの ORM の考え方がリポジトリの本来の考え方と衝突し始め、最終的には EF でリポジトリを決して使用しないという要求に至り、それをアンチパターンと呼びました。

さらに多くのレイヤー

モデル間の親子関係によって多くの混乱が生じます。人が含まれる部門エンティティのようなものです。部門リポジトリは人を含むモデルを返す必要がありますか?たぶんそうではありません。では、リポジトリを部門 (人なし) と人に分けて、個別の抽象化を行ってビジネス モデルにマッピングしてはどうでしょうか?

ビジネス層をサブレイヤーに分割すると、実際には混乱が増大します。たとえば、ほとんどの人がビジネス サービスと呼んでいるものは、特定のビジネス ロジックを特定の種類のビジネス モデルにのみ適用することを抽象化したものです。アプリが人を操作するので、「人」というモデルがあるとします。人を処理するクラスは PeopleService になります。これは、PeopleRepository を介して永続層からビジネス モデルを取得しますが、データ モデルとビジネス モデルの間のマッピングや、人にのみ関連する特定の作業 (ユーザーの計算など) など、他のことも実行します。給料。ただし、ほとんどのビジネス ロジックは複数のタイプのモデルを使用するため、サービスは最終的にリポジトリ上にラッパーをマッピングすることになり、追加の責任はほとんどありません。

次に、EF を使用してデータにアクセスしていると想像してください。 SQL テーブルにマップするエンティティのコレクションを含む DbContext クラスをすでに宣言する必要があります。 LINQ を使用してそれらを繰り返し、フィルタリングし、マッピングします。これはバックグラウンドで SQL コマンドに効率的に変換され、階層的な親子構造を備えた必要なものを提供します。この変換では、特定の列挙型や奇妙なデータ構造などの内部ビジネス データ型のマッピングも処理されます。では、なぜリポジトリ、さらにはサービスも必要なのでしょうか?

抽象化の層を増やすことは無意味なオーバーヘッドのように見えるかもしれませんが、プロジェクトに対する人間の理解を深め、変更の速度と質を向上させると私は信じています。明らかにバランスがあり、すべてのソフトウェア設計パターンをどこでも使用するという明白な要件を備えてシステムが設計されているのを見てきました。抽象化は、コードの読みやすさと関心の分離を向上させる場合にのみ役立ちます。

理由

EF が面倒になる状況の 1 つは単体テストです。 DbContext は複雑なシステムであり、多大な労力をかけて手動でモックする必要がある依存関係が多数あります。そこで Microsoft は、インメモリ データベース プロバイダーというアイデアを思いつきました。したがって、何かをテストするには、メモリ内のデータベースを使用するだけで完了します。

Microsoft のページでは、このテスト方法は現在「非推奨」とマークされていることに注意してください。また、これらの例でも、EF はリポジトリによって抽象化されていることに注意してください。

メモリ内データベースのテストは機能しますが、対処が難しいいくつかの問題が追加されます。

  • メモリ内 DbContext を設定するには、既存のエンティティへのすべての依存関係が必要です
  • 各テストのメモリ データベースのセットアップと起動が遅い
  • 有効なデータベース出力を取得するには、アトミックにテストしたいもの以外にもさらに多くの設定を行う必要があります

したがって、最終的には、「ヘルパー」メソッド内でデータベース内のすべてを設定し、この不可解で複雑なメソッドで始まるテストを作成して、最小の機能さえテストすることになります。 EF コードを含むコードは、このセットアップなしではテストできません。

リポジトリを使用する理由の 1 つは、テストの抽象化を DbContext の上に移動することです。これで、データベースはまったく必要なくなり、リポジトリのモックだけが必要になります。次に、実際のデータベースを使用して統合テストでリポジトリ自体をテストします。インメモリ データベースは実際のデータベースに非常に似ていますが、少し異なります。

もう 1 つの理由は、実生活で実際の価値があることをほとんど見たことがないと認めますが、データへのアクセス方法を変更する必要があるかもしれないということです。おそらく、NoSql または何らかのメモリ分散キャッシュ システムに変更したいと思われるでしょう。あるいは、可能性の方が高いのは、データベース構造 (おそらくモノリシック データベース) から始めて、それを異なるテーブル構造を持つ複数のデータベースにリファクタリングしたいと考えていることです。初めに言っておきますが、これはリポジトリなしでは不可能です。

Entity Framework に特有のことですが、取得するエンティティはデータベースにマップされたアクティブなレコードです。あるエンティティに変更を加え、その変更を別のエンティティに保存すると、データベース内の最初のエンティティも突然更新されてしまいます。あるいは、何かを含めていないか、コンテキストが変更されているため、含めていない可能性があります。

EF の支持者は、エンティティの追跡を非常に肯定的なものとして常に誇大宣伝します。データベースからエンティティを取得し、何らかの処理を行ってから、エンティティを更新して保存するとします。リポジトリを使用すると、データを取得してからビジネスを実行し、その後、少しの更新を実行するためにデータを再度取得します。 EF はそれをメモリに保持し、変更前に更新されていないことを認識しているため、それを 2 回読み取ることはありません。それは本当だ。これらは、データベースの変更を何らかの形で認識し、特に指示がない限り、データベースから処理するすべてのものを追跡するデータベースのメモリ キャッシュについて説明しています。データベース エントリを複雑な C# エンティティに双方向にマップし、深く埋め込まれながら変更を前後に追跡します。ビジネスコードで。個人的には、この多大な責任と懸念事項の分離の欠如は、それを使用することで得られるパフォーマンスよりもはるかに有害であると信じています。さらに、最初の努力で、ビジネス、キャッシュ、データ アクセスの間の明確な境界線を保ちながら、すべての機能をリポジトリ内で抽象化することも、場合によってはリポジトリのメモリ キャッシュの別の層でさえも抽象化することもできます。

実際、これらすべてにおける実際の困難は、別々の関心事を持つべきシステム間の境界を決定することです。たとえば、フィルタリング ロジックをデータベース内のストアド プロシージャに移動すると、パフォーマンスが大幅に向上しますが、使用されるアルゴリズムのテスト容易性と可読性が失われます。逆に、EF またはその他のメカニズムを使用してすべてのロジックをコードに移動することは、パフォーマンスが低下し、場合によっては実現不可能です。あるいは、データ エンティティがビジネス エンティティになるポイントはどこですか (部門と個人に関する上記の例を参照)?

おそらく最良の戦略は、まずこれらの境界線を定義し、次にどのテクノロジーとデザインがその境界線に適合するかを決定することです。

私の結論

私は、リポジトリがその下で Entity Framework や他の ORM を使用している場合でも、サービスとリポジトリの抽象化を常に使用する必要があると考えています。それはすべて、関心の分離に帰着します。私は Entity Framework が有用なソフトウェア抽象化であるとは決して考えません。Entity Framework には非常に多くの負荷が伴うため、コード内で抽象化するにはリポジトリがよく使用されます。 EF は便利な抽象化ですが、ソフトウェアではなくデータベース アクセスに使用されます。

私のソフトウェア作成の哲学は、アプリケーション要件から始めて、それらの要件に対応するコンポーネントを作成し、インターフェースを使用して下位レベルの機能を抽象化するというものです。次に、次のレベルでこのプロセスを繰り返し、コードが読みやすいこと、および現在のレベルで使用されているコンポーネントを理解する必要がないことを常に確認します。そうでない場合は、懸念事項の分離が不十分です。したがって、ビジネス アプリケーションには特定のデータベースや ORM を使用する要件がなかったので、データ層の抽象化によってそれらに関するすべての情報が隠蔽されるはずです。

ビジネスは何を望んでいますか?フィルタリングされた人物のリスト? var people = service.GetFilteredListOfPeople(filter);それ以下でもそれ以上でもありません。そしてサービスメソッドは単に return mapPeople(repo.GetFilteredListOfPeople(mappedFilter)); を実行します。繰り返しますが、それ以下でもそれ以上でもありません。リポジトリがどのように人々を獲得するか、人々を救うか、またはその他のことを行うかは、サービスの関心事ではありません。キャッシュが必要な場合は、IPeopleRepository を実装し、IPeopleRepository に依存するキャッシュ メカニズムを実装します。マッピングが必要な場合は、正しい IMapper インターフェイスを実装してください。などなど。

この記事が冗長になりすぎていないことを願っています。これはソフトウェアの問題ではなく概念的な問題であるため、コード例は特に記載しませんでした。ここでの私の不満のほとんどは Entity Framework に向けられているかもしれませんが、これは小さなことは魔法のように助けてくれるが、重要なことは壊してしまうあらゆるシステムに当てはまります。

お役に立てば幸いです!

以上がORM を含むリポジトリを使用したコード内でのデータ アクセスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
C現代の世界:アプリケーションと産業C現代の世界:アプリケーションと産業Apr 23, 2025 am 12:10 AM

Cは、現代世界で広く使用され、重要です。 1)ゲーム開発において、Cは、非現実的や統一など、その高性能と多型に広く使用されています。 2)金融取引システムでは、Cの低レイテンシと高スループットが最初の選択となり、高周波取引とリアルタイムのデータ分析に適しています。

C XMLライブラリ:オプションの比較と対照C XMLライブラリ:オプションの比較と対照Apr 22, 2025 am 12:05 AM

C:tinyxml-2、pugixml、xerces-c、およびrapidxmlには、一般的に使用される4つのXMLライブラリがあります。 1.TinyXML-2は、リソースが限られている環境、軽量ではあるが機能が限られていることに適しています。 2。PUGIXMLは高速で、複雑なXML構造に適したXPathクエリをサポートしています。 3.Xerces-Cは強力で、DOMとSAXの解像度をサポートし、複雑な処理に適しています。 4。RapidXMLはパフォーマンスと分割に非常に高速に焦点を当てていますが、XPathクエリをサポートしていません。

CおよびXML:関係とサポートの調査CおよびXML:関係とサポートの調査Apr 21, 2025 am 12:02 AM

Cは、サードパーティライブラリ(TinyXML、PUGIXML、XERCES-Cなど)を介してXMLと相互作用します。 1)ライブラリを使用してXMLファイルを解析し、それらをC処理可能なデータ構造に変換します。 2)XMLを生成するときは、Cデータ構造をXML形式に変換します。 3)実際のアプリケーションでは、XMLが構成ファイルとデータ交換に使用されることがよくあり、開発効率を向上させます。

C#対C:重要な違​​いと類似点を理解するC#対C:重要な違​​いと類似点を理解するApr 20, 2025 am 12:03 AM

C#とCの主な違いは、構文、パフォーマンス、アプリケーションシナリオです。 1)C#構文はより簡潔で、ガベージコレクションをサポートし、.NETフレームワーク開発に適しています。 2)Cはパフォーマンスが高く、手動メモリ管理が必要であり、システムプログラミングとゲーム開発でよく使用されます。

C#対C:歴史、進化、将来の見通しC#対C:歴史、進化、将来の見通しApr 19, 2025 am 12:07 AM

C#とCの歴史と進化はユニークであり、将来の見通しも異なります。 1.Cは、1983年にBjarnestrostrupによって発明され、オブジェクト指向のプログラミングをC言語に導入しました。その進化プロセスには、C 11の自動キーワードとラムダ式の導入など、複数の標準化が含まれます。C20概念とコルーチンの導入、将来のパフォーマンスとシステムレベルのプログラミングに焦点を当てます。 2.C#は2000年にMicrosoftによってリリースされました。CとJavaの利点を組み合わせて、その進化はシンプルさと生産性に焦点を当てています。たとえば、C#2.0はジェネリックを導入し、C#5.0は非同期プログラミングを導入しました。これは、将来の開発者の生産性とクラウドコンピューティングに焦点を当てます。

C#対C:学習曲線と開発者エクスペリエンスC#対C:学習曲線と開発者エクスペリエンスApr 18, 2025 am 12:13 AM

C#とCおよび開発者の経験の学習曲線には大きな違いがあります。 1)C#の学習曲線は比較的フラットであり、迅速な開発およびエンタープライズレベルのアプリケーションに適しています。 2)Cの学習曲線は急勾配であり、高性能および低レベルの制御シナリオに適しています。

C#対C:オブジェクト指向のプログラミングと機能C#対C:オブジェクト指向のプログラミングと機能Apr 17, 2025 am 12:02 AM

オブジェクト指向プログラミング(OOP)のC#とCの実装と機能には大きな違いがあります。 1)C#のクラス定義と構文はより簡潔であり、LINQなどの高度な機能をサポートします。 2)Cは、システムプログラミングと高性能のニーズに適した、より細かい粒状制御を提供します。どちらにも独自の利点があり、選択は特定のアプリケーションシナリオに基づいている必要があります。

XMLからCへ:データ変換と操作XMLからCへ:データ変換と操作Apr 16, 2025 am 12:08 AM

XMLからCへの変換とデータ操作の実行は、次の手順で達成できます。1)TinyXML2ライブラリを使用してXMLファイルを解析する、2)データのデータ構造にデータをマッピングし、3)データ操作のためのSTD :: VectorなどのC標準ライブラリを使用します。これらの手順を通じて、XMLから変換されたデータを処理および効率的に操作できます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!