3

RavenDB をデータ ストアとして使用して、シングル ページ アプリケーション (SPA) を構築する予定です。

SPA 作品の ASP.NET ホット タオル テンプレートから始めたいと思います。

EntityFramework/WebApi/Breeze コンポーネントを削除し、ストレージ用の RavenDB とバックエンド API の構築用の ServiceStack に置き換えます。

現在の意見のほとんどは、RavenDB の上にあらゆる種類のリポジトリまたは追加の抽象化を使用することに眉をひそめ、RavenDB API をコントローラー内で (MVC アプリで) 直接使用することを求めているようです。

ServiceStack で Raven を使用し、サービス実装内で直接 IDocumentSession に対して呼び出しを行う場合も、同じ知恵に従うべきだと思います。

私の懸念は、この道をたどると、サービスの実装がかなり肥大化するように見えるという事実にあります。また、たとえば、複数の異なる Web サービス エンドポイント内でユーザー ドキュメントを更新する必要がある場合など、同じコードを何度も記述する必要があるようです。

また、アプリケーションの他の (将来の) 部分から Raven にアクセスする必要があるようです。たとえば、将来、キューからジョブを処理するコンソール アプリケーションを追加する必要があるかもしれません。また、アプリのこの部分が Raven 内のデータにアクセスする必要があるかもしれません。しかし、最初から Raven への唯一のパスは、 Web サービス API。この理論上のコンソール アプリから Web API を呼び出すだけでよいでしょうか? それらが同じハードウェア上で実行されている可能性がある場合、効率が悪いように見えます。

このドキュメント ストアを使用する際のベスト プラクティスに従いながら、私の Web サービスやその他の場所で Raven を効果的に利用する方法についてアドバイスをくれる人はいますか? raven に対する呼び出しを直接処理する中間のビジネス ロジック層を作成することは実用的と思われます...私の Web サービスがこの層内のメソッドを呼び出せるようにします。これは理にかなっていますか?

編集

同様のアーキテクチャの最近のサンプルを提供できる人はいますか?

4

2 に答える 2

7

FWIW、現在 ServiceStack と RavenDB を使用してアプリに取り組んでいます。私たちは DDD アプローチを使用しており、豊富なドメイン レイヤーにビジネス ロジックを配置しています。アーキテクチャは次のとおりです。

  1. ウェブアプリ。Web クライアント コード (SPA) とサービス層をホストします。

  2. サービス層。Domain オブジェクトから完全に分離されたクリーンでかなりフラットな DTO を備えた ServiceStack を使用する Web サービス。Web サービスは、トランザクションとすべての RavenDB のやり取りを管理します。ほとんどの「コマンドっぽい」サービス操作は、a) リクエストによって識別されるドメイン オブジェクト (ドキュメント) をロードする、b) ビジネス ロジックを呼び出す、c) 結果を応答 DTO に変換する、で構成されます。多くの Command-ish 操作が、コードを必要とせずに上記のすべてを実行する自動ハンドラーを使用するように、ServiceStack を拡張しました。「クエリっぽい」サービス操作は、通常、a) RavenDB に対してクエリを実行する、b) クエリ結果を応答 DTO に変換する (実際には、これは a の一部として行われることが多い)、クエリ処理中に RavenDB を使用する/インデックス/トランス)。

  3. ドメイン層。DDD で言えば「ルート集約」に対応するドキュメントは、完全にデータベースに依存しません。ドメイン オブジェクトは、パブリック GETTER のみを公開し、プライベート SETTER を公開します。ドメイン オブジェクトの状態を変更する唯一の方法は、メソッドを呼び出すことです。ドメイン オブジェクトは、サービス レイヤーで使用することを意図したパブリック メソッド、またはドメイン レイヤー内で使用するための保護/内部メソッドを公開します。ドメイン レイヤーは Messages アセンブリを参照します。これは主に、ドメイン オブジェクトのメソッドが複雑な要求オブジェクトを受け入れ、非常に長いパラメーター リストを持つメソッドを回避できるようにするためです。

  4. メッセージの組み立て。単体テストや統合テストなど、他のネイティブ .Net クライアントをサポートするスタンドアロン アセンブリ。

他のクライアントに関しては、2 つのオプションがあります。ServiceStack.Common と Messages アセンブリを参照して、Web サービスを呼び出すことができます。または、必要性が大幅に異なり、Web サービスをバイパスしたい場合は、新しいクライアント アプリを作成し、ドメイン レイヤー アセンブリと Raven クライアントを参照して、その方法で直接作業することができます。

私の見解では、リポジトリ パターンは不必要で漏れやすい抽象化です。私たちはまだ開発中ですが、上記は今のところうまく機能しているようです。

編集

大幅に単純化されたドメイン オブジェクトは、次のようになります。

public class Order
{
    public string Id { get; private set; }
    public DateTime Raised { get; private set; }
    public Money TotalValue { get; private set; }
    public Money TotalTax { get; private set; }
    public List<OrderItem> Items { get; private set; }

    // Available to the service layer.
    public Order(Messages.CreateOrder request, IOrderNumberGenerator numberGenerator, ITaxCalculator taxCalculator)
    {
        Raised = DateTime.UtcNow;
        Id = numberGenerator.Generate();
        Items = new List<OrderItem>();
        foreach(var item in request.InitialItems)
            AddOrderItem(item);
        UpdateTotals(taxCalculator);
    }

    private void AddOrderItemCore(Messages.AddOrderItem request)
    {
        Items.Add(new OrderItem(this, request));
    }

    // Available to the service layer.
    public void AddOrderItem(Messages.AddOrderItem request, ITaxCalculator taxCalculator)
    {
        AddOrderItemCore(request);
        UpdateTotals(taxCalculator);
    }

    private void UpdateTotals(ITaxCalculator taxCalculator)
    {
        TotalTax = Items.Sum(x => taxCalculator.Calculate(this, x));
        TotalValue = Items.Sum(x => x.Value);
    }
}
于 2013-07-11T01:18:00.763 に答える
2

ここで考慮すべき 2 つの主要な部分があります。

まず、すでに述べたように、より熱狂的な RavenDB ファンの言葉を借りれば、それは一般に受け入れられている優れたアプリケーション設計の法則から除外され、自由にアプリケーション全体に浸透することを許可されるべき、神話上の獣です。

もちろん状況にもよりますが、簡単に言えば、SQL Server などで特定の方法でアプリケーションを構成する場合は、RavenDB でも同じようにします。DAL レイヤー、ORM、リポジトリ パターンなど、SQL Server バックエンドを使用する場合は、RavenDB で同じことを行います。漏れやすい抽象化を気にしない場合、またはプロジェクトが小さすぎてデータ アクセスの抽象化がまったく保証されない場合は、それに応じてコーディングしてください。

RavenDB との主な違いは、作業単位や「無料」の ORM などのいくつかのものを取得できることですが、全体的なソリューション アーキテクチャはそれほど変わらないはずです。

次に、他のクライアントを接続します。コンソール アプリ (またはその他のクライアント) が RavenDB サーバー インスタンスに Web サイトに異なる方法でアクセスするのはなぜでしょうか? ASP.NET アプリケーションでサーバー組み込みモードを実行している場合でも、同じ RavenDB.Client コードを使用して他のクライアントをそれに接続できます。Web サービス API に直接触れる必要はありません。

于 2013-07-10T05:48:56.027 に答える