Orchard CMSは独自の方法を使用して、MigrationおよびSchemeBuilderを介してデータスキーマを作成します。 NHiberanateセッション(ISession)およびトランザクションにアクセスするには、これらのオブジェクトを内部にカプセル化する特殊なインターフェース(ISessionHolderおよびITransactionManager)が使用されます。 独自のリポジトリインターフェイス(IRepository)は編成されており、その実装はNHibernate Linqクエリの上で機能します。
Orchardは、デフォルトではNHibernateへの直接アクセスを提供しません。 以下では、Orchard CMSに基づくドメインモデルの構築と使用の機能、およびNHibernateをそのモジュールから直接使用する方法について検討します。
ビジネスレイヤーが個別にカプセル化され、Orchard.CMSがWebサービスを使用してエンティティにアクセスする場合、ドメインモデルの構築の問題は発生しません。 これは大規模プロジェクトに適用されます。 この記事の研究は、Orchard CMSとビジネスロジックエンティティの両方に共通のベースを使用することが最初に計画されているプロジェクトに有効です。
Orchard.CMS(ContentTypeDefinition)に基づくドメインモデル
Orchard.CMSのコアBlogモジュールのBlogPostモデルを検討してください。 (プロジェクトのソースコードは公式ウェブサイトで見つけることができます)。 BlogPostブログタイプモデル:
- BlogPost-コンテンツのタイプ(BlogPost-ContentTypeDefinition)。 次の部分で構成されています。
- BlogPostPart-ブログの説明を担当するコンテンツパーツ。
- CommonPartは、作成者とバージョンに関する情報をカプセル化する標準コンテンツパーツです。
- PublishLaterPart-ドラフトを実装するためのコンテンツパーツ。
- TitlePart-タイトル部分。
- AutoroutPart-美しいURL。
- BodyPart-ブログエントリの実際の本文。
ブログモジュールには、最新のN個のブログエントリを表示するためのウィジェットが実装されています。 このリストを取得するために形成されるSQLクエリを見てみましょう。 これを行うには、NHProfilerを使用し、Orchard.CMSのSoNerdy.NHProfモジュールをプラグインします。 (Orchard.CMSで開発する際の推奨事項の1つは、NHibernate Profiler www.hibernatingrhinos.com/products/nhprofを使用することです 。このユーティリティは、サイトの分析と最適化に不可欠です。)
N個のブログエントリを選択するクエリは次のとおりです。 追加のコンテンツパーツの結合フィールドは、基本パーツに焦点を合わせるために特に削除されました。
SELECT top 12 ... FROM v1__Orchard_Framework_ContentItemVersionRecord this_ inner join v1__Orchard_Framework_ContentItemRecord contentite1_ on this_.ContentItemRecord_id = contentite1_.Id inner join v1__Common_CommonPartRecord commonpart3_ on contentite1_.Id = commonpart3_.Id inner join v1__Orchard_Framework_ContentTypeRecord contenttyp2_ on contentite1_.ContentType_id = contenttyp2_.Id WHERE contenttyp2_.Name in ('BlogPost' /* @p0 */) and commonpart3_.Container_id = 22 /* @p1 */ and this_.Published = 1 /* @p2 */ ORDER BY commonpart3_.CreatedUtc desc
リクエストの簡単な分析:
- コンテンツタイプの基本情報のみを取得するには、少なくとも3つの内部結合が必要です。
- Orchard.CMSで定義されているすべてのコンテンツタイプの基本構造は、ContentItemVersionRecord、ContentItemRecordおよびContentTypeRecordのテーブルに含まれています。
Orchard.CMSコンテンツタイプのフレームワーク内でアプリケーションのドメインモデルを実装した結果は次のようになります。
- すべてのエンティティは、同じテーブルにデータを持ちます。 たとえば、eコマースの場合、Id製品、注文、顧客は同じテーブルに保存されます。
- 小さなクエリでも、コンテンツパーツに関するすべての情報が選択されます。 たとえば、リストの製品の下に表示する製造元の名前を取得する必要がある場合。 Orchard実装の一部として、コンテンツパーツのすべてのデータが選択されます。 そうしないと、動的表現の手法(Shape)を使用する意味が失われます。
- データベースから直接レポートを作成するタスクは非常に複雑です。 たくさんの参加。
- この実装のフレームワークでデータベースを使用してデータを移行することは非常に簡単です。 たくさんの参加。
- 過剰なリクエストによるパフォーマンスの低下。 プロファイラーを使用してボトルネックを特定するには、多くの注意を払う必要があります。
- Orchard.CMSは、コンテンツパーツとコンテンツタイプに基づいています。 テキストセクション、ブログ、htmlパーツなど-ほとんどの場合、コンテンツタイプまたはコンテンツパーツ。 プレゼンテーションデータとアプリケーションドメインモデルの混在は、カプセル化の重大な違反です。
- Orchardのコンテキストで実行されたドメインモデルとビジネスロジックを別のCMSまたは純粋なMVCに転送するのは大きな仕事です。
- テストでは、Orchardコンテキストのフレームワーク内で実行する必要があります。
問題を解決するオプションとして-ドメインモデルを構築する際にコンテンツタイプの使用を完全に放棄します。 シンプルなRecordクラスを使用した実装。 Orchardは、AutoMappingを使用してNHibernateを構成します。慣例の1つは、すべてのデータ型名にレコードの接尾辞を追加する必要があることです。 欠点は、テストが依然としてオーチャードコンテキストに依存し、別のコンテンツ管理システムへの移行がより複雑になることです。 さらに、ビジネスロジック用とプレゼンテーション用に別々のモジュールを実装する必要があります。
Orchard.CMSでNHibernateを直接使用する
フレームワークOrchard.CMSは、OrchardパイプラインなしでHNibernateを構成し、その機能を直接使用する機能を提供します。 バージョン1.7以降、新しいISessionConfigurationEventsインターフェイスが利用可能になりました。 デモプロジェクトでのISessionConfigurationEventsの実装例:
public class PersistenceConfiguration : ISessionConfigurationEvents { public PersistenceConfiguration() { Logger = NullLogger.Instance; } public ILogger Logger { get; set; } public void Created(FluentConfiguration cfg, AutoPersistenceModel defaultModel) { cfg.Mappings(x => x.FluentMappings.AddFromAssemblyOf<Customer>()); } ... public void ComputingHash(Hash hash) { hash.AddString("NHStore.Domain.Mapping"); } }
モジュールを構成するには、このインターフェイスの実装をモジュールに追加し、CreatedメソッドでNHibernate構成を定義する必要があります。 また、一般的なNHibernate構成の自動再生成のためにハッシュモジュールを定義する必要があります。 Orchard.CMSは、App_Data \ Sites \ Defaultフォルダにあるmapping.binファイルにNHibernate構成を生成します。これはサイトごとに個別の構成です。 既存の構成を再生成するには、マッピングファイルを削除する必要があります。アプリケーションが自動的に作成します。
エンティティにアクセスするには、Orchard.CMSの既存のインターフェイスを使用できます。
IRepositoryは、Linq To NHibernate Cacheble Queryによって実装される標準インターフェイス実装です。 主な方法:
- void Create(Tエンティティ); -保存
- void Update(Tエンティティ); -エビクト/マージ
- void Delete(Tエンティティ); -削除
- IEnumerable Fetch(); -ToReadOnlyCollection
- IQueryableテーブル{get; }-LinqToNHibernateクエリオブジェクト
ISessionLocator-ISessionインターフェイスオブジェクトへのアクセスを提供するOrchard.CMSのインターフェイス。 主な方法:
- ISession For(Type entityType); -エンティティのタイプが送信され、ログにのみ使用されます(Logger.Debug( "{0}のセッションを取得"、entityType);セッションオブジェクトは、リクエストごとに作成されます。
オーチャードでの取引について言及する必要があります。 デフォルトでは、Orchard.CMSはリクエスト全体に対して1つのトランザクションを作成し、リクエストの完了後にコミットを実行します。 要求が成功した場合、コミットが実行され、失敗した場合、トランザクションはロールバックされます。 デフォルトのデータ分離レベルはReadCommittedです。 現在のトランザクションを完了して新しいトランザクションを開くには、ITransactionManagerインターフェイスを使用する必要があります。 このインターフェイスは、トランザクションを操作するためのメソッドを提供します。
別のアセンブリで定義されたドメインモデルのFluent NHibernate Mapping構成を使用して、デモプロジェクトをテストおよび実装できました。 プロジェクトはgithubにあり、 ダウンロードできます 。
この記事は、Orchard.CMSを使用したプロジェクトの実装に関する推奨事項です。 このコンテンツ管理システムのフレームワークでドメインモデルを実装するための他の効果的なアプローチがコメントに記載されている場合、私はうれしいです。