【问题标题】:ASP.NET MVC 3 EF CodeFirst - DBContext item editingASP.NET MVC 3 EF Code First - DBContext 项编辑
【发布时间】:2011-10-26 09:16:46
【问题描述】:

我为此沮丧了一天...请帮忙。

我有一个发票部分,我可以在其中通过使用 JQuery 附加/删除 DOM 元素来动态添加新项目...我已经想出了如何正确命名这些元素,以便它们正确地映射到模型并发送到动作参数。

假设我的控制器中有一个名为 Edit 的操作,参数类型为 Invoice

[HttpPost]
public virtual ActionResult Edit(Invoice invoice) {
    if (ModelState.IsValid) {
         //code discussed below
    }
    return RedirectToAction("Index");
}

invoice 参数包含我想要的所有数据。我对此没有问题。以下是对象模型。

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

【问题讨论】:

  • 当您说“无法添加项目”时,究竟是什么意思?这是否意味着产生了异常?如果有,有什么例外?
  • 是的,你能发布例外吗?

标签: asp.net entity-framework asp.net-mvc-3 ef-code-first dbcontext


【解决方案1】:

DbEntityEntry.CurrentValues.SetValues 只更新标量和复数属性。它不关心导航属性。这就是为什么您的InvoiceItems 集合中的更改不会写入数据库的原因。同样的问题是将Invoice 的状态设置为Modified。这只会将标量和复杂属性标记为已修改,而不是任何导航属性。

不幸的是,EF 没有提供一种简单的方法来分析导航集合中的哪些项目已添加、删除或仅与数据库中的原始状态相比进行了修改(如果在实体分离时已完成更改)从上下文(在您的示例中的网页上)。

这意味着您必须自己对数据库中的原始状态和新更改的状态进行比较。

如何做到这一点的代码示例在此处的答案中,例如:The relationship could not be changed because one or more of the foreign-key properties is non-nullable 这些示例非常适合您的情况,只需将ParentItem 替换为Invoice 并将ChildItems 替换为InvoiceItems

您还可以查看几天前的这个问题以获取更多信息:WCF, Entity Framework 4.1 and Entity's State 实际上还有许多其他问题与缺乏对更新分离对象图的支持(即一个非常常见的场景)是实体框架更令人不快的限制之一。

(注意:在 MVC 控制器中有 UpdateModel 方法。我不确定此方法是否能够更新完整的对象图(添加、删除和更改集合中的项目)。我个人不知道'不要使用它,如果我会使用它,则不要使用 DB 模型,仅用于 ViewModel 更新。)

【讨论】:

  • 谢谢,这正是我需要的信息:)
猜你喜欢
  • 1970-01-01
  • 2016-06-10
  • 2011-08-27
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2012-03-15
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多