7

私は一日のようにこれによって挫折しました...助けてください。ASP.NET MVC 3 EF CodeFirst - DBContextアイテムの編集

私は、JQueryを使用してDOM要素を追加/削除することで新しい項目を動的に追加できる請求書セクションを持っています...これらの要素の名前を正しく指定する方法はすでにわかっていますモデルを作成し、アクションパラメータに送信します。

それでは、私は種類の請求書のPARAM

[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; } 
} 

そして、それが私が立ち往生しているところです。

私はインボイスコレクション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に新しいupdateメソッドを追加:

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:修正

+0

"アイテムを追加できません"と言うと、それはどういう意味ですか?例外が生成されたことを意味しますか?もしそうなら、例外は何ですか? –

+0

はい、例外を掲示してください。 – Jack

答えて

6

DbEntityEntry.CurrentValues.SetValuesは、スカラーと複雑なプロパティを更新します。ナビゲーションプロパティは気にしません。そのため、InvoiceItemsコレクションの変更がデータベースに書き込まれないのはこのためです。同じ問題は、Invoiceの状態をModifiedに設定することです。これはスカラーと複合プロパティを変更したもののマークしますが、ナビゲーションプロパティはマークしません。

残念なことに、EFでは、ナビゲーションコレクション内のどのアイテムが、エンティティが存在する間に変更が行われた場合、データベースの元の状態と比較して追加、削除、または変更されたかを分析する簡単な方法はありません(あなたの例ではWebページ上の)コンテキストから切り離されています。

これは、データベースの元の状態と新しい変更された状態との比較を自分で行う必要があることを意味します。例えば、ここでの回答にある行う方法

コード例:The relationship could not be changed because one or more of the foreign-key properties is non-nullable例はちょうどInvoiceItemsによってInvoiceChildItemsParentItemを置き換える、自分の状況に非常によく合います。

また、数日前の追加情報については、この質問をご覧ください:WCF, Entity Framework 4.1 and Entity's Stateデタッチされたオブジェクトグラフの更新がサポートされていないという同じ問題に関連する他の多くの質問があります。かなり一般的なシナリオ)は、Entity Frameworkのより不快な制限の1つです。

(ワンノート:MVCコントローラでUpdateModel方法がある私は(追加、削除、コレクション内の項目を変更)このメソッドは、完全なオブジェクトグラフを更新することが可能であるかどうかわからないんだけど個人的に私は「ドン。それを使用して、それを使用して、DBモデルで作業するのではなく、ViewModelの更新だけを使用する場合)。

+0

ありがとう、それは私が必要な情報です:) – Mirek

関連する問題