- - PR -
親子テーブルのクラス設計につきまして
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-07-22 16:13
表題の件ですが、皆様のご意見を拝借したく投稿させて頂きました。
N階層アーキテクチャを採用し、各階層間のデータの受け渡しは、カスタムクラス(データクラス)でやり取りしています。 //Orderのビジネスロジッククラス //といっても殆どの場合、ビジネスロジックは特に無く下記の例のように //データアクセス層(DAL)のメソッド(UpdateOrder)を呼び出しているだけです。(汗) BLL.Order{ GetAllOrder(); GetOrderById(int orderId); UpdateOrder(OrderInfo orderInfo){ 例: return DAL.UpdateOrder(orderInfo) }; InsertOrder(OrderInfo orderInfo); DeleteOrder(int orderId); } //OrderDetailのビジネスロジッククラス BLL.OrderDetail{ GetOrderDetailById(int orderDetailId); GetOrderDetailByOrderId(int orderId); UpdateOrderDetail(OrderDetailInfo orderDetailInfo); InsertOrderDetail(OrderDetailInfo orderDetailInfo); DeleteOrderDetail(int orderDetailId); } //Orderのカスタムクラス OrderInfo{ int orderId DateTime orderDate . . } //OrderDetailのカスタムクラス OrderDetailInfo{ int orderDetailId int orderId int itemId decimal price . . } 現状、親子関係のテーブルなどは特に考慮せずに取得する場合は、下記のように取得しています。 /*Order.aspx.cs*/ //オーダー情報を取得 OrderInfo orderInfo = Order.GetOrderById(1234); //オーダー明細情報を取得 List<orderDetailInfo) orderDetailInfo = OrderDetail.GetOrderDetailByOrderId(1234); これまで見たサンプルアプリ等では、OrderInfoの中にOrderDetailInfoを含み OrderとOrderDetailの情報を同時に取得するケースを良く見ました。 下記の図を参照下さい。 //Orderのカスタムクラス OrderInfo{ int orderId DateTime orderDate ↓ココです OrderDetailInfo orderDetailInfo . } 更新処理は、下記のような流れです。 /*Order.aspx.cs*/ using(TransactionScope ts= new TransactionScope()){ //オーダーを更新 int newOrderId = Order.UpdateOrder(OrderItemInfo); //オーダー明細の数だけループ処理 for(int i=0; i<OrderDetailInfo.Count; i++){ //オーダー明細を更新 OrderDetail.UpdateOrderDetail(orderDetailInfo[i]); } ts.Complete(); } ここで質問なのですが、OderInfoの中にOrderDetailInfoを持たせた方が ベターでしょうか? Orderテーブルの内容だけ参照したい場合、OrderDetailは特に必要ないケース などがあります。 また更新処理ですが、Transactionなどの処理はビジネスロジックレイヤーにいれるべきものでしょうか? そうなった場合、やはりOderInfoの中にOrderDetailInfoを持たせる必要があるかと思います。 クラス設計の考え方でアドバイスをいただけると幸いです。 宜しくお願いいたします。 【環境 VS2005 C# Webアプリ】 | ||||||||
|
投稿日時: 2008-07-22 17:34
>OderInfoの中にOrderDetailInfoを持たせた方がベターでしょうか?
ベター。 OrderInfoとOrderDetailInfoに関連を持たせたい。 >OrderDetailは特に必要ないケースなどがあります。 OrderDetailInfoはオンデマンドで取得する仕組みにする。 詳細が必要な時、初めて詳細取得を(勝手に・自動で)行うようにすれば良いだけ。 >Transactionなどの処理はビジネスロジックレイヤーにいれるべきものでしょうか? びみょう・・・けーすばいけーす・・・。 私的には・・・含めませんね・・・。 あとは・・・ OrderDetailInfoにはOrderIDは持たせず、OrderInfoへの参照を持たせるかな。 コンストラクタもOrderIDではなく、OrderInfoを受け取る形で。 (そうしないと親と子に違うOrderIDを渡すミスが発生するかも!? しれませんよね・・・) と、思った次第です・・・。 | ||||||||
|
投稿日時: 2008-07-22 18:19
くまっちさん、
ご返信いただきましてありがとうございます。 私なりに理解しようとしましたが、幾つかすっきり理解できない 部分がありましたので、ご教授いただけますでしょうか?
下記のようにOrderInfoのプロパティーのGetterでOrderDetailInfoを取得すると いう認識でよろしいでしょうか? でもこれだと、このプロパティーにアクセスする度に、OrderDetailInfoを取得してしまう(汗) private List<OrderDetailInfo> orderDetail; public List<OrderDetailInfo> OrderDetail { get { return BLL.OrderDetail.GetOrderDetailByOrderID(orderId); } set { OrderDetail = value; } }
ちょっと『OrderInfoへの参照を持たせるかな。 コンストラクタもOrderIDではなく、OrderInfoを受け取る形で』 の部分が理解できなかったです。 現在、OrderDetailInfoの引数付きのコンストラクタは以下のようですが、 ここで、 orderIdの代わりにOrderInfoを渡すという事でしょうか? public OrderDetailInfo() { } public OrderDetailInfo(int orderDetailId, int orderId, int itemId...){ this.OrderDetailId = orderDetailId; this.OrderId = orderId; . . } | ||||||||
|
投稿日時: 2008-07-22 18:23
OrderInfo と OrderDetailInfo は密接な関係にあるので、集約パターンを適用するといいと思います。(で、そうすると OrderDetail クラスは不要となるはずです。) Aggregates(集約)パターン OrderDetail が特に必要ないケースもあるかと思いますが、基本的に集約内のエンティティはまとめて扱います。 どうしても OrderDetailInfo を読み込みたくない場合は、レイジーロードパターンを使用すれば OrderInfo から OrderDetailInfo を取得可能にしつつ、OrderDetailInfo が必要になるまで読み込みを遅延させることができます。 PofEAA's Wiki - LazyLoad LINQ to SQL とか O/R マッパーはレイジーロードをサポートしてたりします。自前で実装する場合は↓を参考にしてみてください。(※ レイジーロードにはこの他にも種類があります) C#と諸々 仮想プロキシによるレイジーロード # あと、クラスの名前付けが適切でない気がします。 # PofEAA's Wiki - LazyLoad へのリンクと※部分を追加しました。 _________________ C#と諸々 [ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 18:25 ] [ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 18:34 ] | ||||||||
|
投稿日時: 2008-07-22 19:25
よこけんさんが全て説明されていますが・・・
こんな感じにすればいいのではないでしょうか。 (あくまでサンプルっすよ) 【コンストラクタについて】
【オンデマンド読み込み】(↓OrderInfoクラス内です)
オンデマンド読み込みは、よこけんさんの提示しているレイジーロードってのとやってる事は同じです。 [コメント追加] [ メッセージ編集済み 編集者: くまっち 編集日時 2008-07-22 19:28 ] | ||||||||
|
投稿日時: 2008-07-22 20:18
よこけん様、
ご回答いただきましてありがとうございます。 よこけん様のブログを以前拝見させて頂いた事がありました。 リンク先など勉強になりました。レイジーロードなど軽く見た事がありましたが、 どういった場面でつかうものかさっぱり分らなかったのですが、こういった場合に 有効なのですね!
具体的にどこがおかしいか突っ込んでいただけるとうれしいです。 | ||||||||
|
投稿日時: 2008-07-22 20:29
くまっち様、
引き続きご教授いただきましてありがとうございます。 わざわざサンプルコード頂いて嬉しかったです。 大変勉強になりました。 | ||||||||
|
投稿日時: 2008-07-22 22:42
あらま、ありがとうございます。
例えばこんな感じですかね。 Order → OrderRepository OrderDetail → OrderDetailRepository OrderInfo → Order OrderDetailInfo → OrderDetail 特に上 2 つのクラス名は変えた方がいいかと。(〜Repository という名前じゃなくてもいいですが) データストアから注文データを取得したり更新したりするためのクラスの名前が "注文" ではおかしいと思います。 ところで、骨骨★Rock!さんの最初の投稿で > /*Order.aspx.cs*/ と書かれてますが、書き間違いですよね?(aspx じゃないですよね?) _________________ C#と諸々 [ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 22:46 ] |