0

私は Breeze を Durandal (まだ 1.2) で使用していますが、簡単な解決策が見つからない問題に直面しています。以下に説明するように、Invoice と InvoiceLine の 2 つのエンティティがあります。

public class Invoice
{
    [Key]
    public int Id { get; set; }
    public string InvoiceNumber { get; set; }
    public string Comment { get; set; }
    public double? TotalExclVAT { get; set; }        
    public double? TotalInclVAT { get; set; }
    public double? TotalVAT { get; set; }
    public bool? WithoutVAT { get; set; }
    public virtual List<InvoiceLine> Lines { get; set; }
}

public class InvoiceLine
{
    [Key]
    public int Id { get; set; }
    public string Description { get; set; }
    public double VatPercent { get; set; }
    public double Amount { get; set; }
    public int InvoiceId { get; set; }
    public virtual Invoice Invoice { get; set; }
}

2 つのケースで請求書の合計 (TotalExclVAT、TotalInclVAT、TotalVAT) を計算する必要があります。

  1. 誰かが請求明細行を追加/変更したとき。

  2. 誰かがWithoutVAT請求書のフラグを変更したとき。

この計算クライアント側を実行するのは良い考えではないと思います。このサーバー側での実行は、主にセキュリティ上の理由から優れています。

BeforeSaveEntity私が最初に考えたのは、Invoice と InvoiceLine で仕事をすることでした。

これが私がしたことです:

public bool BeforeSaveEntity(EntityState entityState, EntityInfo entityInfo)
{
    var invoice = entityInfo.Entity as Invoice;
    ...
    ComputeTotal(entityInfo, invoice);
}

private void ComputeTotal(EntityInfo entityInfo, Invoice invoice)
{
    var query = Context.InvoiceLines.Where(x => x.invoiceId == invoice.Id).AsEnumerable();
    double totalExclVAT = 0;
    double totalVAT = 0;
    int percent = 0;

    foreach (var line in query.ToList())
    {
        totalExclVAT = ...
        totalVAT = ...
    }

    entityInfo.OriginalValuesMap.Add("TotalExclVAT", invoice.TotalExclVAT);
    entityInfo.OriginalValuesMap.Add("TotalInclVAT", invoice.TotalInclVAT);
    entityInfo.OriginalValuesMap.Add("TotalVAT", invoice.TotalVAT);
    accounting.TotalExclVAT = totalExclVAT;
    accounting.TotalInclVAT = totalExclVAT + totalVAT;
    accounting.TotalVAT = totalVAT;
}

請求明細行についても同じことが行われます。ComputeTotal 関数でわかるように、クエリを実行して DB から請求書の行を取得し、合計を計算して結果を請求書に保存します。

請求書に新しい行を追加する場合、データベースでクエリを実行しても、この追加された行が取得されません! まだDBに保存されていないためです。

クライアント側で進めた方が楽だったのですが、これは良い考えではないと思います... そうですか?

ですから、別の方法があると確信していますが、自分では見つけられません。

どんな助けでも大歓迎です。


アップデート

以下は、この問題の最初のショットです。

    public Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
    {
        List<EntityInfo> invoices;
        List<EntityInfo> invoiceLines;
        EntityInfo ei;

        if (!saveMap.TryGetValue(typeof(InvoiceLine), out invoiceLines))
        {
            // if we fall here it means no invoice lines exists in the saveMap
        }

        if (!saveMap.TryGetValue(typeof(Invoice), out invoices))
        {
            // if we fall here it means no invoices exists in the saveMap
            // >> getting the invoice from DB and add it to the map
            using (var dc = new BreezeContext())
            {
                int invoiceId = ((InvoiceLine)invoiceLines[0].Entity).InvoiceId;
                EFContextProvider<BreezeContext> cp = new EFContextProvider<BreezeContext>();
                var acc = dc.Invoices.Where(x => x.Id == invoiceId).FirstOrDefault();
                ei = cp.CreateEntityInfo(acc, Breeze.WebApi.EntityState.Modified);
                invoices = new List<EntityInfo>();
                saveMap.Add(typeof(Invoice), invoices);
                invoices.Add(ei);
            }
        }

        // There is only 1 invoice at a time in the saveMap
        Invoice invoice = (Invoice)invoices[0].Entity;
        ei = invoices[0];
        Dictionary<int, InvoiceLine> hashset = new Dictionary<int, InvoiceLine>();

        // Retrieving values of invoice lines from database (server side)
        using (var dc = new BreezeContext())
        {
            var linesServerSide = dc.InvoiceLines.Where(x => x.InvoiceId == invoice.Id).AsEnumerable();

            foreach (var elm in linesServerSide)
            {
                hashset.Add(elm.Id, elm);
            }
        }

        // Retrieving values of invoice lines from modified lines (client side) 
        foreach (var entityInfo in invoiceLines)
        {
            InvoiceLine entity = (InvoiceLine)entityInfo.Entity;
            switch (entityInfo.EntityState)
            {
                case Breeze.WebApi.EntityState.Added:
                    hashset.Add(entity.Id, entity);
                    break;
                case Breeze.WebApi.EntityState.Deleted:
                    hashset.Remove(entity.Id);
                    break;
                case Breeze.WebApi.EntityState.Modified:
                    hashset.Remove(entity.Id);
                    hashset.Add(entity.Id, entity);
                    break;
            }
        }

        // Computing totals based on my hashset
        double totalExclVAT = 0;
        double totalInclVAT = 0;
        double totalVAT = 0;

        foreach (var elm in hashset)
        {
            InvoiceLine line = elm.Value;
            totalExclVAT += line.Amount;
            totalVAT += line.Amount * (int)line.VatPercent.Value / 100;
        }
        totalInclVAT = totalExclVAT + totalVAT;

        // Adding keys if necessary
        if (!ei.OriginalValuesMap.ContainsKey("TotalExclVAT"))
            ei.OriginalValuesMap.Add("TotalExclVAT", invoice.TotalExclVAT);
        if (!ei.OriginalValuesMap.ContainsKey("TotalInclVAT"))
            ei.OriginalValuesMap.Add("TotalInclVAT", invoice.TotalInclVAT);
        if (!ei.OriginalValuesMap.ContainsKey("TotalVAT"))
            ei.OriginalValuesMap.Add("TotalVAT", invoice.TotalVAT);

        // Modifying total values
        invoice.TotalExclVAT = totalExclVAT;
        invoice.TotalInclVAT = totalInclVAT;
        invoice.TotalVAT = totalVAT;

        return saveMap;
    }

請求書とinvoiceLinesがクライアント側で変更された場合は常に、上記のソリューションがうまく機能します。請求書がクライアント側で変更されていない場合に問題があります (行のみが変更されます)。この場合、関連する請求書を DB から取得して saveMap に追加する必要があります。ご覧のとおり、それが私のコードで行っていることです。しかし、ここで手動で変更した for プロパティにキーを追加する必要がOriginalValuesMapあります。この場合、辞書オブジェクトが null であるため、追加できません。それから私がするとき...

ei.OriginalValuesMap.Add("TotalExclVAT", invoice.TotalExclVAT);

... null オブジェクト (OriginalValuesMap) では機能しません。

したがって、私の新しい問題は次のとおりです。DBに既に存在するsaveMapにエンティティを追加する方法です。したがって、このエンティティを としてマークしたくはありませei = cp.CreateEntityInfo(acc, Breeze.WebApi.EntityState.Add);ei = cp.CreateEntityInfo(acc, Breeze.WebApi.EntityState.Modified);。この場合、私の OriginalValuesMap は null であり、問​​題があるようです。

ここで説明しようとしていることを理解していただければ幸いです。

4

1 に答える 1

0

これにトリガーされたストアド プロシージャを使用しない理由はありますか? これは確かに最も簡単なアプローチでしょう...

しかし...もしあれば、他のアプローチは「BeforeSaveEntity」の代わりに「BeforeSaveEntities」を使用することです。これにより、「SaveMap」全体にアクセスできるようになります。

次に、変更された請求書ごとにすべてのinvoiceLinesのハッシュセットを作成し、これを、この請求書に関連付けられたクライアント側のinvoiceLinesでオーバーレイされた請求書ごとの請求書明細のサーバー側クエリの組み合わせとして構築します(SaveMapから)。次に、各 hashSet を合計し、これを使用して「Totalxxx」プロパティを更新します。

少し簡潔ですが、うまくいけばこれは理にかなっています。

于 2013-09-05T17:34:07.647 に答える