3

ORM で生成されたオブジェクトの使用方法がわかりません。データベース モデルをオブジェクトにマッピングするために LLBLGen を使用しています。これらのオブジェクトは、私たちのビジネス モデルを表す別のレイヤーにカプセル化します (私が思うに)。

たぶん、このコードはこれをよりよく説明します。

public class Book { // The class as used in our application
    private BookEntity book;      // LLBLGen entity
    private BookType bookType;    // BookType is another class that wraps an entity

    public Book(int Id) {
        book = new BookEntity(Id);
    }

    public BookType BookType {
        get { return this.bookType; }
        set { 
            this.bookType = value; 
            this.book.BookType = new BookTypeEntity(value.ID);
            this.book.Save();
        }
    }

    public int CountPages() { }  // Example business method
}

エンティティのフィールドをプロパティのように公開するのは面倒です。マッピングをやり直すからです。リスト型では、「追加」および「削除」メソッドに加えてリストを公開するプロパティを作成する必要があるため、さらに悪化します。

上記の BookType セッターの例では、BookTypeEntity オブジェクトにアクセスする必要があります。BookType オブジェクトの ID を使用して新しいオブジェクトをインスタンス化することで、このオブジェクトを取得できます。これも気持ち悪い。

BookEntity オブジェクトを拡張してそこにビジネス ロジックを追加するべきではないのでしょうか? それともパーシャルを使用しますか?

LLGLGen の例では、エンティティ オブジェクトを直接使用していますが、これは非常に面倒に見えます。上記のコードで、ビジネス ロジック (CountPages など) のメソッドを持つこともできるオブジェクトが必要です。

4

3 に答える 3

5

マッピングに LLBLGen を使用したことはありませんが、使用した ORM ツールのほとんどは部分クラスを生成します。次に、これらのオブジェクトに追加したいカスタム コード/ロジックを別のファイルに追加します (部分クラスが再生成されても上書きされないようにします)。

かなりうまくいくようです。ORM から部分クラスを取得できない場合は、データ オブジェクトをビジネス ロジックでラップする Facade を作成します。このようにして 2 つが分離され、もう一方を上書きせずに一方を再生成できます。

アップデート

部分クラスは、部分クラスの 1 つの宣言でインターフェイスの実装をサポートし、他の宣言ではサポートしません。インターフェイスを実装する場合は、カスタム コードの部分ファイルに実装できます。

MSDNから直接:

partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

に等しい

class Earth : Planet, IRotate, IRevolve { }
于 2009-06-24T12:43:47.170 に答える
3

LLGLGenで可能かどうかはわかりませんが、ORMを操作するときに私が一般的に行うことは、例のIBookで永続化されたクラスへのインターフェイスを作成することです。このインターフェイスは、ラッピング クラスのパブリック ゲッターを介して公開します。このようにして、必要に応じて、フィールドにカスタム動作を追加する必要がある場合に、必要に応じて IBook を拡張できます。

一般的に言えば、ORM エンティティをドメインに「マッピング」する方法は 3 つあります。

  1. 投稿した方法です。基本的に、すべてを再マップします
  2. 私が投稿した方法で、ORMエンティティをインターフェースとして公開します
  3. ORM エンティティを直接公開する

#1 は好きではありません。アプリケーションに 2 つのマッピングがあるのは好きではないからです。DRY、KISS、YAGNI はすべてこれに違反しています。

#3は好きではありません。ドメイン層の消費者層がORM層と直接通信するようになるからです。

..だから、私は#2で行きます.3つの悪の中で小さいようです;)

[更新] 小さなコード スニペット :)

データ層の ORM 生成クラス:

public class Book : IBook
{
   public string ISBN {get; private set;}
}

IBook は、ブック ラッパーと共に、ビジネス ロジック レイヤーにあります。

public interface IBook
{
    string ISBN {get;}
}

public class BookWrapper   //Or whatever you want to call it :)
{
    //Create a new book in the constructor
    public BookWrapper()
    {
        BookData = new Data.MyORM.CreateNewBook();
    }

    //Expose the IBook, so we dont have to cascade the ISBN calls to it
    public IBook BookData {get; protected set;}
    //Also add whichever business logic operation we need here
    public Author LookUpAuther()
    {
       if (IBook == null)
          throw new SystemException("Noes, this bookwrapper doesn't have an IBook :(")
       //Contact some webservice to find the author of the book, based on the ISBN
    }
}

これが認識可能なデザインパターンかどうかはわかりませんが、私が使用しているものであり、これまでのところ非常にうまく機能しています:)

于 2009-06-24T12:42:33.397 に答える
1

リレーショナル データとオブジェクトのさまざまなパラダイム間の不一致の痛みを感じています。

これは、リレーショナル データとオブジェクトの世界が互いに大きく異なることを意味します。たとえば、データベースランドでは、すべてのデータが公開されています。オブジェクトランドでは、データはカプセル化され、特に公開されません。データベース ランドでは、すべての関係は双方向ですが、オブジェクト ランドでは、コレクション内のオブジェクトはその親への参照を持たない場合があります。データベースランドでは、手順はグローバルです。オブジェクトランドでは、プロシージャは、作用したデータを含むオブジェクトに対してローカルです。

これらの理由やその他の理由から、データベース テーブルを表すオブジェクトを作成するアプローチは、本質的に苦痛を伴います。はい、技術的にはオブジェクトですが、データベースランドのセマンティクスを持っています。あなたが経験したように、それらをオブジェクトランドに住まわせることは、不可能ではないにしても困難です。これは、data-firstと呼ばれます。

(私の意見では) より良いアプローチは、データベースをオブジェクトにマッピングするのではなく、オブジェクトをデータベースにマッピングすることに集中することです。これはobject-firstと呼ばれ、 NHibernateによって非常によくサポートされています。このアプローチは、データベースがシステムの実装の詳細であり、設計の指針ではないという事実を強調しています。

これがあなたの質問に具体的に答えているわけではないことは承知していますが、エンティティを概念化するのに苦労している理由について、いくつかのコンテキストを提供してくれることを願っています.最初にテーブルであり、次にエンティティです.

于 2009-08-23T17:42:04.467 に答える