0

私のドメインにはProject、基本的に、プロジェクトがexecuted. プロジェクトが実行されると、膨大な量のLogEntries. 私のアプリケーションでは、特定のプロジェクトのこれらのログ エントリを分析する必要があるため、データベース (Oracle) からログ エントリの一部 (時間枠) を部分的に連続してロードできる必要があります。この関係を DB テーブルおよびオブジェクトとしてどのようにモデル化しますか?

私はProjectテーブルとProjectLogテーブルを持ち、主キーへの外部キーを持ち、Projectオブジェクトレベルで「同じ」ことを行い、クラスProjectとプロパティを持つことができます

IEnumerable<LogEntry> LogEntries { get; }

NHibernate にすべてのマッピングを行わせます。しかし、この場合、ProjectRepository をどのように設計すればよいでしょうか? 私は方法を持つことができました

void FillLog(Project projectToFill, DateTime start, DateTime end);

誰かがこのメソッドを呼び出すまで LogEntries をロードしないように NHibernate に指示するにはどうすればよいですか? また、NHibernate にそのメソッド内の特定の時間枠をロードさせるにはどうすればよいですか?

私はORMにかなり慣れていません。おそらく、その設計はNHibernateまたは一般的に最適ではありませんか? 多分私はそれを別の方法で設計する必要がありますか?

4

2 に答える 2

2

Project エンティティを集約ルートとして持つ代わりに、参照を移動しLogEntryProductプロパティを持たせ、集約ルートとしても機能させてみませんか。

public class LogEntry
{
    public virtual Product Product { get; set; }
    // ...other properties
}

public class Product
{
    // remove the LogEntries property from Product
    // public virtual IList<LogEntry> LogEntries { get; set; }
}

これらのエンティティは両方とも集約ルートであるため、 と の 2 つの異なるリポジトリが存在することにProductRepositoryなりLogEntryRepositoryます。LogEntryRepositoryメソッドを持つことができますGetByProductAndTime

IEnumerable<LogEntry> GetByProductAndTime(Project project, DateTime start, DateTime end);
于 2012-06-19T16:06:44.707 に答える
1

NHibernateで部分的/フィルター済み/基準ベースのリストをロードする「正しい」方法は、クエリを使用することです。ありますがlazy="extra"、それはあなたが望むことをしません。

すでに述べたように、これはRootAggregate->ChildrenのDDDモデルを壊します。私は絶対的な年齢でこの問題に苦労しました。何よりもまず、永続性に相当するものがドメインモデルの汚染に関係することを嫌い、APIサーフェスを「正しく」見せることができなかったからです。所有するエンティティクラスのフィルターメソッドは機能しますが、きれいにはほど遠いです。

結局、私はエンティティ基本クラスを拡張することに決めました(すべてのエンティティはそれを継承します。最近は少し流行遅れですが、少なくともこの種のことを一貫して実行できます)Query<T>()、LINQを使用するという保護されたメソッドを使用します関係を定義する式であり、リポジトリの内部でLINQ-to-NHを呼び出し、必要に応じてIQueryable<T>クエリできるを返します。次に、通常のプロパティの下にある呼び出しをファサードできます。

基本クラスはこれを行います:

protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
        where TCollection : class, IPersistent
    {
        return Repository.For<TCollection>().Where(selector);
    }

(ここで、私のリポジトリ実装はIQueryable<T>直接実装し、作業をNHに委任することに注意してくださいSession.Query<T>()

そして、ファサードは次のように機能します。

public virtual IQueryable<Form> Forms 
{ 
    get 
    { 
         return Query<Form>(x => x.Account == this); 
    } 
}

これは、アカウントとフォームの間のリスト関係を、実際にマップされた関係の逆として定義します([フォーム]-> [アカウント])。

「無限の」コレクションの場合(セット内に無制限の数のオブジェクトが存在する可能性がある場合)、これは問題なく機能しますが、NHibernateで関係を直接マップできないため、NHクエリでプロパティを直接使用できないことを意味します。間接的に。

私たちが本当に必要としているのは、LINQプロバイダーを使用してリストに直接クエリを実行する方法を知っているNHibernateの汎用バッグ、リスト、およびセットの実装の代わりです。1つはパッチとして提案されています(https://nhibernate.jira.com/browse/NH-2319を参照)。パッチが完成または受け入れられていないことがわかります。また、提案者がこれを拡張機能として再パッケージ化していないことがわかります。DiegoMijelshonはここSOのユーザーなので、おそらく彼はチャイムを鳴らします...彼の提案したコードをPOCとしてテストし、宣伝どおりに機能しますが、明らかにテストも保証もされておらず、必ずしも完全ではありません。副作用がある可能性があり、使用または公開する許可がなければ、とにかく使用できません。

NHチームがこれを実現するパッチの作成/承認に取り掛かるまで、そしてそれを行わない限り、回避策に頼り続ける必要があります。NHとDDDは、ここで相反する世界観を持っています。

于 2012-06-20T12:33:11.807 に答える