私は一日のようにこれに不満を感じています...助けてください。
JQueryを使用してDOM要素を追加/削除することで新しいアイテムを動的に追加できる請求書セクションがあります...これらの要素に正しく名前を付ける方法をすでに理解しているため、モデルに適切にマッピングされて送信されますアクションパラメータに。
したがって、コントローラーに「請求書」タイプのパラメーターを使用した「編集」というアクションがあるとします。
[HttpPost]
public virtual ActionResult Edit(Invoice invoice) {
if (ModelState.IsValid) {
//code discussed below
}
return RedirectToAction("Index");
}
請求書パラメータには、必要なすべてのデータが含まれています。私はこれに問題はありません。以下はオブジェクトモデルです。
public class Invoice
{
[Key]
public int ID { get; set; }
public InvoiceType InvoiceType { get; set; }
public string Description { get; set; }
public int Amount { get; set; }
public virtual ICollection<InvoiceItem> InvoiceItems { get; set; }
}
InvoiceItemsコレクションに注意してください。これには、動的に挿入された請求書アイテムのコレクションが含まれています。以下はInvoiceItemモデルです
[Table("InvoiceItems")]
public class InvoiceItem
{
[Key]
public int ID { get; set; }
[ForeignKey("Invoice")]
public int InvoiceID { get; set; }
public Invoice Invoice { get; set; }
public string Description { get; set; }
public int Amount { get; set; }
}
そして、それは私が立ち往生しているところです。
InvoiceコレクションInvoiceItemsのアイテムをデータベースに挿入/更新できません。私はたくさんグーグルしていて、これらの解決策を見つけました-残念ながら、これらのどれもうまくいきません。
解決策#1 -SetValuesを使用した奇妙なコード:
Invoice origInvoice = db.Invoices.Single(x => x.ID == invoice.ID);
var entry = db.Entry(origInvoice);
entry.OriginalValues.SetValues(invoice);
entry.CurrentValues.SetValues(invoice);
db.SaveChanges();
解決策#2-新しい更新メソッドをDbContextに追加します。
public void Update<T>(T entity) where T : class
{
this.Set<T>().Attach(entity);
base.ObjectContext.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified);
}
解決策#3 - http://blogs.msdn.com/b/adonet/archive/2011/01/29/using-dbcontext-in-ef-feature-ctp5-partに従って、既存の変更されたエンティティをコンテキストにアタッチする-4-add-attach-and-entity-states.aspx
db.Entry(invoice).State = EntityState.Modified;
db.SaveChanges();
ソリューション#1の仕組み:新しく追加されたInvoiceItemsを除くすべてのプロパティを更新します。SetValues()はICollectionプロパティを無視します。これは、db.SaveChanges();の直前にこの行を追加した場合に機能します。
origEntry.Entity.InvoiceItems = invoice.InvoiceItems;
...しかし、これが正しいアプローチだとはまったく思いません。
ソリューション#2の仕組み: DbContextクラスにObjectContextプロパティがないため、まったく機能しません。
ソリューション#3の仕組み:このソリューションは請求書を更新しますが、それ以外の場合はInvoiceItemsを無視します。
追加情報:以下は、InvoiceItemプロパティにマップされるアイテム要素を生成するために使用されるJavaScriptの一部です。
window.InvoiceItemIndex++;
var str = $.tmpl("itemRowTmpl", {
itemIndexes: '<input type="hidden" name="Invoice.InvoiceItems.Index" value="' + window.InvoiceItemIndex + '"/> \
<input type="hidden" name="Invoice.InvoiceItems[' + window.InvoiceItemIndex + '].ID" value="0"/>\
<input type="hidden" name="Invoice.InvoiceItems[' + window.InvoiceItemIndex + '].InvoiceID" value="@Model.Invoice.ID"/>',
itemDescription: '<textarea cols="150" name="Invoice.InvoiceItems[' + window.InvoiceItemIndex + '].Description" rows="2"></textarea>',
itemAmount: '<input type="text" class="InvoiceItemAmount" style="text-align:right;" name="Invoice.InvoiceItems[' + window.InvoiceItemIndex + '].Amount" />',
});
最後の質問:私は何が間違っているのですか?別のモデルに関連するアイテムの新しいコレクションがデータベースに自動的に挿入されることの何が問題になっていますか?親モデルが正常に更新されたときに、なぜ無視されるのですか?
編集1:修正