10

DTO

多くのユーザーに拡張したい Web アプリケーションを構築しています。また、Web サービスを介して信頼できるサード パーティに機能を公開する必要があります。

LLBLGen を使用してデータ アクセス レイヤーを生成しています (SQL Server 2008 を使用)。目標は、Web アプリを DAL の詳細から保護するビジネス ロジック層を構築すること、そしてもちろん、DAL を超えた追加レベルの検証を提供することです。また、現時点でわかる限り、Web サービスは基本的に BLL のシン ラッパーになります。

もちろん、DAL には独自のエンティティ オブジェクトのセット (CustomerEntity、ProductEntity など) があります。ただし、これらのオブジェクトには DAL 固有のメソッドが含まれており、アセンブリは DAL に固有であるなどの理由から、プレゼンテーション レイヤーがこれらのオブジェクトに直接アクセスできるようにしたくありません。したがって、アイデアはデータ転送オブジェクト (DTO) を作成することです。アイデアは、これらは本質的に、実際にはデータベース テーブル Customer である CustomerEntity のすべてのフィールドを持ち、おそらく一部の IsChanged/IsDirty プロパティを除いて、他のものではない単純な古い C#/.NET オブジェクトになるということです。したがって、CustomerDTO、ProductDTO などがあります。これらは基本 DTO クラスから継承されると思います。LLBLGen のテンプレートを使用してこれらを生成できると思いますが、まだ確信が持てません。

そのため、BLL はこれらの DTO オブジェクトを受け入れて返すことにより、その機能を公開するという考え方です。Web サービスは、それを使用するサード パーティのためにこれらのオブジェクトを XML に変換することを処理すると思いますが、多くは .NET を使用していない可能性があります (また、JSON を使用して、Web アプリの AJAX 呼び出しからスクリプトを呼び出すことができるものもあります)。

これを設計する最善の方法と、正確にどのように進めるかはわかりません。ここにいくつかの問題があります:

1) これをクライアントにどのように公開する必要があるか (プレゼンテーション層と Web サービス コード)

これらのメソッドを持つ1つのパブリッククラスがあり、すべての呼び出しがアトミック操作になると考えていました:

InsertDTO、UpdateDTO、DeleteDTO、GetProducts、GetProductByCustomer など...

次に、クライアントはこれらのメソッドを呼び出して、適切な引数 (通常は DTO) を渡します。

これは良い、実行可能なアプローチですか?

2) これらのメソッドから何を返すか? 明らかに、Get/Fetch のようなメソッドは DTO を返します。しかし、インサートはどうですか?署名の一部は次のようになります。

InsertDTO(DTO dto)

ただし、何を挿入するときに何を返す必要がありますか? エラーの通知を受け取りたい。ただし、一部のテーブルには自動インクリメント主キーを使用します (ただし、いくつかのテーブルには、特に多対多の自然キーがあります)。

私が考えた 1 つのオプションは Result クラスでした。

class Result
{
    public Exception Error {get; set;}
    public DTO AffectedObject {get; set;}
}

したがって、挿入時に、DTO は get ID (CustomerDTO.CustomerID など) プロパティ セットを取得し、この結果オブジェクトに配置します。クライアントは、Result.Error != null の場合にエラーがあるかどうかを認識し、Result.AffectedObject プロパティから ID を認識します。

これは良いアプローチですか?1 つの問題は、冗長な大量のデータをやり取りしているように見えることです (ID だけの場合)。一部の挿入にはそのような自動インクリメントキーがないため、「int NewID」プロパティを追加してもきれいになるとは思いません。もう 1 つの問題は、Web サービスがこれをうまく処理できるとは思わないということですか? 派生DTOではなく、ResultクラスのAffectedObjectのベースDTOを返すだけだと思います。さまざまな種類の Result オブジェクト (おそらくベースの Result から派生し、Error プロパティを継承する) をたくさん持つことでこれを解決できると思いますが、それはあまりきれいに見えません。

わかりました、これが言い過ぎではないことを願っていますが、明確にしたいと思います。

4

2 に答える 2

3

1: これは非常に標準的なアプローチであり、最適な単体テスト可能なアプローチの「リポジトリ」実装に適しています。

2: 例外 (WCF 境界で "障害" として宣言する必要があります) は自動的に発生します。それを直接処理する必要はありません。データの場合、次の 3 つの一般的なアプローチがあります。

  • 契約での使用ref(あまりきれいではありません)
  • (更新された)オブジェクトを返します-つまりpublic DTO SomeOperation(DTO item);
  • 更新された ID 情報 (主キー / タイムスタンプ / など) のみを返す

これらすべてについての 1 つのことは、操作ごとに異なる型を必要としないことです ( ResultDTO ごとに複製する必要があるクラスと比較してください)。

于 2009-02-22T08:59:53.627 に答える
1

Q1: この問題を解決するために、WCF データ コントラクト複合型を DTO と考えることができます。このようにして、UI レイヤーは DataContract の DataMember プロパティにのみアクセスできます。アトミック操作は、WCF インターフェイスによって公開されるメソッドになります。

Q2: 主キーなどを含む新しいカスタム型を返すように Response データ コントラクトを構成します。WCF は、例外を UI にバブル バックするように構成することもできます。

于 2009-02-22T08:12:35.707 に答える