簡易ORMフレームワークを作成してみる(20)

更新系の利用例として、引き続き以前作成したハンバーガショップのモデルを題材にしてみます。更新系なのでお買い上げを実装してみます。
まずは、お買い上げの型指定されたDataSetを作成します。

今回は、お買い上げのトランザクションに関連するテーブルのみで構成していますが、店舗や商品も含める方法もあります。商品を含めない代わり、今回お買い上げに商品DataSetを渡するようにしました*1。共通化の方針やデータアクセスの効率などを含めて選択していきます。今回は商品の再利用性を重視し、お買い上げに商品を含めないようにしました。

また、今回プレゼンテーションでの利用を踏まえた工夫をいくつか追加しています。ドメインモデルをデータバインドするだけで自動的に暫定の合計金額を表示できるようになっています。

[Test]
public void お買い上げ()
{
    商品DataSet itemModel = new 商品DataSet();
    DataSetDataAdapter itemDa = new SqlDataSetDataAdapter(itemModel.商品);
    itemDa.Fill(itemModel, null, FillPolicy.AllData);

    店舗DataSet storeModel = new 店舗DataSet();
    DataSetDataAdapter storeDa = new SqlDataSetDataAdapter(storeModel.店舗);
    storeDa.Fill(storeModel, null, FillPolicy.AllData);

    DataSetDataAdapter salesDa = new SqlDataSetDataAdapter(new お買い上げDataSet().お買い上げ);
    お買い上げDataSet salesModel = new お買い上げDataSet(itemModel);

    お買い上げ sale = salesModel.お買い上げ作成(storeModel.FindBy店舗名("店舗1").店舗ID);
    お買い上げ明細 big = sale.明細追加(itemModel.FindBy商品名("ビッグマ○クセット"), 1);
    Assert.AreEqual(580, sale.税抜き合計金額);
    sale.明細追加(itemModel.FindBy商品名("ハンバーガ"), 2);
    Assert.AreEqual(780, sale.税抜き合計金額);
    big.オプション追加(itemModel.FindBy商品名("コーラM"));
    Assert.AreEqual(780, sale.税抜き合計金額);
    big.オプション追加(itemModel.FindBy商品名("ポテトL"));
    Assert.AreEqual(810, sale.税抜き合計金額);
    sale.確定();
    Assert.AreEqual(810, sale.税抜き合計金額);
    salesDa.Update(salesModel);

    お買い上げDataSet updtedSalesModel = new お買い上げDataSet(itemModel);
    QueryObject qo = new QueryObject();
    qo.Filter = qo.Eq("お買い上げID", salesModel.お買い上げ[0].お買い上げID);
    salesDa.Fill(updtedSalesModel, qo);
    Assert.AreEqual(810, updtedSalesModel.お買い上げ[0].税抜き合計金額);
}

お買い上げモデル

partial class お買い上げDataSet
{

    public お買い上げDataSet(商品DataSet context) : this()
    {

        _商品Context = context;
    }

    private 商品DataSet _商品Context;
    public 商品DataSet 商品Context
    {
        get { return _商品Context; }
    }

    public お買い上げRow お買い上げ作成(string storeId)
    {
        お買い上げRow newRow = this.お買い上げ.Newお買い上げRow();
        newRow.店舗ID = storeId;
        this.お買い上げ.Addお買い上げRow(newRow);
        return newRow;
    }

    partial class お買い上げRow
    {
        private 商品DataSet 商品Context
        {
            get
            {
                お買い上げDataSet ds = (お買い上げDataSet)this.tableお買い上げ.DataSet;
                return ds.商品Context;
            }
        }

        public 税金 税金
        {
            get { return new 税金(); }
        }
            
        public お買い上げ明細Row 明細追加(商品 item, decimal num)
        {
            お買い上げDataSet ds = (お買い上げDataSet)this.tableお買い上げ.DataSet;
            お買い上げ明細Row newRow = ds.お買い上げ明細.Newお買い上げ明細Row();
            newRow.お買い上げRow = this;
            newRow.商品ID = item.商品ID;
            newRow.数量 = num;
            ds.お買い上げ明細.Addお買い上げ明細Row(newRow);
            foreach (商品 opt in item.必須オプション商品取得())
            {
                newRow.オプション追加(opt);
            }
            this.Update合計金額(false);
            return newRow;
        }

        public void 確定()
        {
            Update合計金額(true);
            this.日時 = DateTime.Now;
        }

        internal void Update合計金額(bool validate)
        {
            decimal amount = 0;
            foreach (お買い上げ明細Row row in this.Getお買い上げ明細Rows())
            {
                商品 item = 商品Context.FindBy商品ID(row.商品ID);
                row.価格 = item.単価取得(row.オプションリスト取得(), validate);
                amount += row.価格 * row.数量;
            }
            this.税抜き合計金額 = amount;
            this.税 = 税金.消費税計算(amount);
            this.税込み合計金額 = amount + this.税;
        }

    }

    partial class お買い上げ明細Row
    {
        private 商品DataSet 商品Context
        {
            get
            {
                お買い上げDataSet ds = (お買い上げDataSet)this.tableお買い上げ明細.DataSet;
                return ds.商品Context;
            }
        }

        public 販売商品明細Row オプション追加(商品 item)
        {
            お買い上げDataSet ds = (お買い上げDataSet)this.tableお買い上げ明細.DataSet;
            販売商品明細Row newRow = ds.table販売商品明細.New販売商品明細Row();
            newRow.お買い上げ明細Row = this;
            newRow.商品ID = item.商品ID;
            ds.table販売商品明細.Add販売商品明細Row(newRow);
            this.お買い上げRow.Update合計金額(false);
            return newRow;
        }

        public List<商品> オプションリスト取得()
        {
            List<商品> optList = new List<商品DataSet.商品Row>();
            foreach (販売商品明細Row item in this.Get販売商品明細Rows())
            {
                optList.Add(商品Context.FindBy商品ID(item.商品ID));
            }
            return optList;
        }
    }
}

*1:ここでの商品DataSetはリポジトリのような位置づけと考えられます