13

私が取り組んでいる現在のシステムでは、Castle Activerecord を利用して、ドメイン オブジェクトとデータベース間の ORM (オブジェクト リレーショナル マッピング) を提供しています。これはすべてうまくいき、ほとんどの場合、実際にうまく機能します。

この問題は、Castle Activerecords の非同期実行のサポート、具体的にはオブジェクトが属するセッションを管理する SessionScope で発生します。要するに、悪いことが起こります!

そのため、ドメイン オブジェクト (DB が存在することを知っていて気にする) から DTO オブジェクト (DB について何も知らず、セッション、マッピング属性などを気にしない) に簡単に変換する (自動的に考える) 方法を探しています。 ORM)。

誰でもこれを行うことについて提案がありますか。まず、オブジェクトの基本的な一対一のマッピングを探しています。ドメイン オブジェクトPersonはPersonDTOと言うようにマッピングされます。もったいないので手動でやりたくありません。

当然反省が頭に浮かびますが、このサイトに出回っているより優れた IT 知識から、「よりクールな」 提案が得られることを期待しています。

ああ、Castle ActiveRecord にマップされる前に述べたように、ORM オブジェクトである C# で作業しています。


コード例:

@ajmastrean のリクエストにより、私が (ひどく) 一緒に嘲笑した例にリンクしました。この例には、キャプチャ フォーム、キャプチャ フォームコントローラドメインオブジェクト、activerecordリポジトリ、および非同期ヘルパーが含まれています。実行に必要な ActiveRecored dll を含めたため、少し大きい (3MB) です。ローカル マシンにActiveRecordAsyncというデータベースを作成するか、.config ファイルを変更する必要があります。

例の基本的な詳細:

キャプチャフォーム

キャプチャ フォームにはコントローラへの参照があります

private CompanyCaptureController MyController { get; set; } 

フォームの初期化時に MyController.Load() private void InitForm () { MyController = new CompanyCaptureController(this); を呼び出します。MyController.Load(); これは LoadComplete() というメソッドに戻ります

public void LoadCompleted (Company loadCompany)
{
    _context.Post(delegate
    {
         CurrentItem = loadCompany;
         bindingSource.DataSource = CurrentItem;
         bindingSource.ResetCurrentItem();
         //TOTO: This line will thow the exception since the session scope used to fetch loadCompany is now gone.
         grdEmployees.DataSource = loadCompany.Employees;
         }, null);
    }
}

これは、遅延ロードとして設定された Company の子リストを使用しているため、 「悪いこと」が発生する場所です。

コントローラー

コントローラーには、フォームから呼び出された Load メソッドがあり、Asyc ヘルパーを呼び出して LoadCompany メソッドを非同期的に呼び出し、Capture フォームの LoadComplete メソッドに戻ります。

public void Load ()
{
    new AsyncListLoad<Company>().BeginLoad(LoadCompany, Form.LoadCompleted);
}

LoadCompany() メソッドは、単純にリポジトリを利用して既知の会社を見つけます。

public Company LoadCompany()
{
    return ActiveRecordRepository<Company>.Find(Setup.company.Identifier);
}

例の残りの部分は一般的なもので、基本クラスから継承する 2 つのドメイン クラス、データを挿入するためのセットアップ ファイル、およびActiveRecordMediator機能を提供するためのリポジトリがあります。

4

5 に答える 5

9

多くの古い Web サービス コントラクトから WCF データ コントラクトにデータをコピーした、これと非常によく似た問題を解決しました。次のような署名を持ついくつかのメソッドを作成しました。

public static T ChangeType<S, T>(this S source) where T : class, new()

このメソッド (または他のオーバーロード) が 2 つの型に対して初めて実行されるときに、各型のプロパティが調べられ、名前と型に基づいて両方に存在するものが決定されます。この「メンバー交差」を取り、DynamicMethod クラスを使用して IL をエミル化し、ソース タイプをターゲット タイプにコピーしてから、結果のデリゲートをスレッドセーフな静的ディクショナリにキャッシュします。

デリゲートが作成されると、それは非常に高速であり、交差基準に一致しないプロパティをコピーするデリゲートを渡すために、他のオーバーロードを提供しました。

public static T ChangeType<S, T>(this S source, Action<S, T> additionalOperations) where T : class, new()

...だから、Person to PersonDTO の例でこれを行うことができます:

Person p = new Person( /* set whatever */);
PersonDTO = p.ChangeType<Person, PersonDTO>();

また、Person と PersonDTO の両方のプロパティ (同じ名前と型を持つもの) は、実行時に発行されたメソッドによってコピーされ、後続の呼び出しは発行される必要はありませんが、それらの型に対して同じ発行されたコードを再利用します。順序(つまり、PersonDTO を Person にコピーすると、コードを発行するためのヒットも発生します)。

投稿するにはコードが多すぎますが、興味があれば、SkyDrive にサンプルをアップロードして、ここにリンクを投稿する努力をします。

リチャード

于 2008-10-04T03:58:16.210 に答える
4

ValueInjecterを使用すると、あらゆるものをあらゆるものにマッピングできます。

  • オブジェクト<->オブジェクト
  • オブジェクト<->フォーム/Webフォーム
  • DataReader->オブジェクト

そしてそれは次のようなクールな機能を持っています:平坦化と非平坦化

ダウンロードにはたくさんのサンプルが含まれています

于 2010-06-15T08:50:09.913 に答える
2

ここでブログを書いたオートマッパーを使用する必要があります。

http://januszstabik.blogspot.com/2010/04/automatically-map-your-heavyweight-orm.html#links

プロパティが両方のオブジェクトで同じ名前である限り、オートマッパーはそれを処理します。

于 2010-04-22T20:52:12.863 に答える
0

実際、私は今完全に混乱しています。あなたが言っているので、「したがって、ドメインオブジェクト(DBが存在することを知っていて気にする)からDTOオブジェクト(DBについて何も知らず、セッションを気にしない)に簡単に変換する(自動的に考える)方法を探しています、属性のマッピング、またはすべての ORM など)"

  1. ドメインオブジェクトは DB を知っていて気にかけていますか? ビジネス ロジックのみを含み、DB と ORM をまったく認識しないことが、ドメイン オブジェクトの全体的なポイントではないでしょうか?....これらのオブジェクトが必要ですか? それらがすべて含まれている場合は、それらを修正する必要があります...そのため、DTOがどのように表示されるかについて少し混乱しています

  2. 遅延読み込みで直面している問題について詳しく教えてください。

于 2008-11-21T23:37:02.690 に答える
0

詳細をここに記載していないことをお詫びしますが、基本的な OO のアプローチは、DTO を ActiveRecord クラスのメンバーにして、ActiveRecord にアクセサーとミューテーターを DTO に委譲させることです。コード生成またはリファクタリング ツールを使用して、AcitveRecord クラスから DTO クラスを非常に迅速に構築できます。

于 2008-10-04T04:21:50.357 に答える