7

以下に示すようなデータベース関係があります。ドメイン オブジェクトは、LINQ to SQL ORM に基づいて作成されます。

支払いは、現金支払いとギフト クーポン支払いで構成されます。購入総額が550であるとします。次のコンポーネントとして支払うことができます

1 Gift Coupon Valued 300

1 Gift Coupon Valued 200

I Cash Currency Valued 50

ここに画像の説明を入力

ORM の「InsertOnSubmit」機能を使用して、新しい支払いレコードを挿入しています。次のコードは正常に動作しています。ただし、会社がクレジット カードを使用する新しい支払いコンポーネントを導入する場合、「支払い」ドメイン クラスを変更する必要があります。ORMを引き続き使用して、支払クラスOpen for Extension および Closed for Changesを作成するにはどうすればよいですか?

注: Payment クラスには動作があります(例: GetTotalAmountCollected)。OCPを満たすために「Payment」クラスを作ろうとしています。

注:クーポン タイプには特定の動作があります。クーポンの発行日が 2000 年 1 月 1 日より前の場合、合計金額の計算に使用しないでください (つまり、CouponValue はゼロにする必要があります)。ストラテジー パターンを使用したコードのリファクタリングも参照してください。

注:.Net 4.0を使用しています

参照:

  1. Entity Framework で ObjectContext.AddObject を使用するとエラーが発生する
  2. 戦略パターンを使用したコードのリファクタリング
  3. 継承よりも構成を優先しますか?
  4. コードファースト vs モデル/データベースファースト
  5. Unity を使用した戦略パターンと依存性注入
  6. デリゲートと OOP による C# ストラテジー デザイン パターン
  7. C# で戦略パターンを使用するには?
  8. EF Code First による継承: パート 2 – タイプごとのテーブル (TPT) http://weblogs.asp.net/manavi/archive/2010/12/28/inheritance-mapping-strategies-with-entity-framework-code-first -ctp5-part-2-table-per-type-tpt.aspx

C# コード:

public class PaymentAppService
{
    public RepositoryLayer.ILijosPaymentRepository Repository { get; set; }

    public void MakePayment()
    {
        DBML_Project.Payment paymentEntity = new DBML_Project.Payment();
        paymentEntity.PaymentID = 1;
        paymentEntity.PaymentType = "PurchaseP";

        DBML_Project.CashPayment cashObj = new DBML_Project.CashPayment();
        cashObj.CashPaymentID = 1;
        cashObj.CurrencyNumber = 123;
        cashObj.CurrencyValue = 100;

        DBML_Project.GiftCouponPayment giftCouponObj = new DBML_Project.GiftCouponPayment();
        giftCouponObj.GiftCouponPaymentID = 1;
        giftCouponObj.CouponValue = 200;
        giftCouponObj.CouponNumber = 124;

        paymentEntity.CashPayments = new System.Data.Linq.EntitySet<DBML_Project.CashPayment>();
        paymentEntity.CashPayments.Add(cashObj);

        paymentEntity.GiftCouponPayments = new System.Data.Linq.EntitySet<DBML_Project.GiftCouponPayment>();
        paymentEntity.GiftCouponPayments.Add(giftCouponObj);

        Repository.InsertEntity(paymentEntity);
        Repository.SubmitChanges();
    }
}

リポジトリ:

public class LijosPaymentRepository : ILijosPaymentRepository
{
    public System.Data.Linq.DataContext MyDataContext { get; set; }

    public void InsertEntity(DBML_Project.Payment payment)
    {
        //Insert the entity
        MyDataContext.GetTable<DBML_Project.Payment>().InsertOnSubmit(payment);
    }

    public void SubmitChanges()
    {
        MyDataContext.SubmitChanges();
    }
}
4

4 に答える 4

2

おそらく、ORM でも継承を利用することが 1 つの代替手段になるでしょう。そのため、N 個のコレクションを持つ代わりに、Payment Entity のタイプごとに 1 つです。同じコレクションにすべてのサブタイプがあります。そして、それらすべてを合計すると、支払い全体が表されます。

もう少し別の名前を付けた方が簡単かもしれません。たとえば、Purchaseの概念を考えてみましょう。Purchase にはPaymentsのコレクションが必要です。Paymentは抽象クラスで、そこからCash Coupon CreditCardすべて継承されます。

モデルをそのように設定すると、特定の問題を解決する方法に関して多くの可能性が開かれます。すべての支払いを同じように扱うことができ、個別のコレクションを忘れることができます。さらに、ポリモーフィズムとダブル ディスパッチによって大幅に制御できます。

そうすれば、新しい支払いタイプが発生した場合でも、モデルは同じままで、新しいサブタイプを持つだけです。

最近のほとんどの ORM は、継承のためのさまざまな永続化スキームをサポートしており、データ構造をきれいに保つのにも役立ちます。

于 2012-07-11T06:35:26.420 に答える
2

支払いの種類ごとに新しい種類を作成することの付加価値は何ですか? 「現金による支払い」と「バウチャーによる支払い」の違いがわかります。その区別をするために2つの異なるタイプがあることに同意できます。

CashPaymentしかし、なぜ a 、 aなどを区別するのCreditCardPaymentでしょうか ... ? 支払いの種類に応じて追加の情報を保存する必要がありますか? 動作は変わりますか?

シンプルに保ち、通常の ' ' 型に追加のプロパティを追加してはPaymentいかがでしょうか。

public class Payment {}

public class VoucherPayment : Payment {}

public class MoneyPayment : Payment
{
    public PaymentMode { get; set; }
}

public enum PaymentMode 
{
    Cash,
    CreditCard
}
于 2012-07-11T08:28:23.613 に答える
1

階層ごとのテーブル (http://msdn.microsoft.com/en-us/library/bb738443) を使用してモデルを定義できます。あなたが行っている支払い。その後、新しい支払いタイプでより多くのデータが必要な場合は、列を追加する必要があります。ただし、EF は、エンティティを定義する方法と、それらのエンティティをデータ ストアにマップする方法に関してかなり柔軟です。おそらく、Number や Value などの共通の列のセットを使用してから、すべて共有して、StringValue1 などの一般的な名前の列をデータベースに追加することができます。次に、それらの列を、ドメインにとってより意味のある概念モデルのより適切な名前のプロパティにマップできます。

これにより、基本的にデータベース スキーマが 1 つのテーブルにフラット化されますが、モデルは個別のクラスのままです。データ ストアや Payment クラスに影響を与えることなく、追加の支払いタイプの Payment クラスをサブクラス化できます。ただし、モデルを変更して新しい支払いタイプを追加し、それらを適切な列にマップする必要があります。

于 2012-07-11T08:06:07.150 に答える