44

ぐるぐる回っている感じです。正しいリポジトリ パターンがLINQ to SQLを使用しているものについて、私は決心できないようです。Rob Conery の MVC Storefrontに精通している場合は、彼の実装が LINQ で生成されたモデルを別のクラスでラップし、LINQ で生成されたモデルを単にデータ転送オブジェクト(DTO) として扱っていることがわかります。次のようになります。

//Custom wrapper class.
namespace Data
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public IList<Address> Addresses {get;set;}
    }
}

//Linq-Generated Class - severly abbreviated
namespace SqlRepository
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public EntitySet<Address> {get;set;}
    }
}

//Customer Repository
namespace SqlRepository
{
    public class UserRepository : IUserRepository
    {
        private _db = new DB(); //This is the Linq-To-Sql datacontext

        public IQueryable GetCusomters()
        {
            return
                from c in _db.Customers
                select new Customer // This is the wrapper class not the gen'd one
                {
                   Id = c.Id,
                   Name = c.Name,
                   Addresses = new LazyList(c.Addresses)
                };
        }

Mike Hadlowが IRepository<T> のバージョンでLINQ to SQL を使用した IRepository パターンの使用で提案している方法とは対照的に、この方法 (ラッパー クラスを使用) の利点は何ですか?リポジトリ?

ビジネス ロジックはどこで適用およびチェックする必要がありますか? これは、保存/更新時にリポジトリによってすべて一緒に呼び出される別のレイヤーにありますか、それともラッパークラスに組み込まれていますか?

4

3 に答える 3

49

問題は、LINQ to SQL は真のオブジェクト リレーション マッパー(ORM) ではなく、データ アクセス レイヤー ジェネレーターであるということです。XML ファイルを手動で編集し、 SqlMetalなどをいじって深く掘り下げることで、ORM にすることができますが、それが輝くのはDALです。

ORM の背後にある考え方は次のとおりです。SQL データベースとドメイン オブジェクトがあります。データベースを適切に設計するには、適切に設計されたオブジェクト モデルに論理的に変換されないこと (正規化など) を行う必要があります。これは「インピーダンスのミスマッチ」と呼ばれ、ORM の役割は、クリーンで効果的かつ効率的な方法でそのミスマッチに対処することです。データベースとのやり取りの負担が少ないことは、ほとんど二次的なものです。

リポジトリの背後にある考え方は、アプリケーションの残りの部分からインフラストラクチャへのすべての永続化ロジックと依存関係をカプセル化することです。アプリケーションで Customer オブジェクトが必要な場合、それが SQL Server、MySQL、XML ファイル、または ASP.NET メンバーシップのいずれから来ているかを知る必要はありません。分離が完了すると、永続化ストーリーに変更を加えても、アプリケーションの残りの部分には影響しません。

それを念頭に置いて、なぜ彼がしたことをしたのかがより明確になります。LINQ to SQL を使用して DAL を生成しますが、DAL について知っておくべき唯一のことはリポジトリであるため、ドメイン オブジェクトへの変換が行われます。こうすることで、永続化のストーリーを気にせずにドメイン モデルをリファクタリングでき、アプリケーションによる波及効果を気にせずにデータベースをリファクタリングできます。また、どの ORM を使用するか、データをどこに保存するかなどの質問を決定する前に、ビジネス ロジックのコーディングを開始することもできました。

彼が実際の ORM ( NHibernateなど) を使用する場合、そのマッピング コードは別の場所 (XML またはブートストラップ クラス) で処理されます。LINQ to SQL (および Robs のオープン ソース DAL、SubSonic ) は素晴らしいプロジェクトだと思いますが、より小規模な 2 層アプリケーション向けに設計されており、リポジトリ パターンのようなものはやり過ぎです。ショップフロントは、NHibernate の追加の複雑さがなぜ重要なのかを示す良い例でもあります。彼は、すべて手動で行うのではなく、そのようなシナリオを処理するために構築されたものを使用することで、多くのコードを節約できたはずです。

于 2009-01-20T22:35:47.447 に答える
13

DTOが定義されている場所と、それをどのようにテストするかによって異なります。DBML を使用する場合、LINQ to SQL はデータ レイヤーでデータ オブジェクトを生成します。LINQ to SQL 永続化の無視をサポートしていますが、それを簡単にするためにわざわざ行っているわけではありません。Entity Frameworkはまったくサポートしていません。

これは、標準モデルでは、データ レイヤーがすべてのドメイン エンティティを定義していることを意味します。これは、データ レイヤーから完全に分離してユーザー インターフェイス/ビジネス レイヤーをテストする場合には注意が必要です。

実用的なアプローチは、単体テストでデータ レイヤーのデータ オブジェクト定義を使用することですが、データ コンテキストは使用しません (つまり、データ コンテキストをリポジトリ インターフェイスの背後に隠し、エンティティ タイプを公開します)。これは、UI などがデータ層を強く参照する必要があることを意味します。しかし、これを「私たちが使用しているかもしれないし、使用していないかもしれないリポジトリ実装もたまたま含むドメインモデルレイヤー」と考えれば、それは正当化されるかもしれません。

ドメイン エンティティを完全に分離すると、単体テストと制御の反転(IoC) がより「純粋」になりますが、所有するコードの量が増えます (非常に両刃)。

于 2009-01-20T11:27:08.780 に答える
2

生成されたオブジェクトはシリアライズ可能ですか? そうじゃないなという印象でした。マーク・グラベルが上で言ったように、それは単なる孤立のケースです.

リポジトリを切り替えて、MySQL、Oracle、XML ファイル、Web サービス、またはその他のデータ プロバイダー (リポジトリ) を使用している場合はどうなるでしょうか。エンティティを参照するために、LINQ to SQL アセンブリに結び付けられますよね? もちろん、これは望ましくありません。

于 2009-01-20T22:22:14.870 に答える