私は 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) を計算する必要があります。
誰かが請求明細行を追加/変更したとき。
誰かが
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 であり、問題があるようです。
ここで説明しようとしていることを理解していただければ幸いです。