将updatemodel与EF4.3.1一起使用时出现InvalidOperationException

Bas*_*nen 6 asp.net-mvc entity-framework asp.net-mvc-3

当我更新我的模型时,我得到一个关于子关系的错误,我也尝试更新.

我的模型,说Order与OrderItem有关系.在我看来,我有订单的详细信息以及orderiteemplate for orderitems.当我更新数据时,Order的链接为null,但orderid已填充,因此它应该能够链接它,TryUpdateModel返回true,但保存失败,但是:

InvalidOperationException:操作失败:无法更改关系,因为一个或多个外键属性不可为空.当对关系进行更改时,相关的外键属性将设置为空值.如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象.

我的更新方法:

    public ActionResult ChangeOrder(Order model)
    {
        var order = this.orderRepository.GetOrder(model.OrderId);

        if (ModelState.IsValid)
        {
            var success = this.TryUpdateModel(order);
        }

        this.orderRepository.Save();

        return this.View(order);
    }
Run Code Online (Sandbox Code Playgroud)

我尝试了在SO和其他来源上看到的所有解决方案,没有成功.

我使用.Net MVC 3,EF 4.3.1和DBContext.

Spi*_*keh 4

这里有很多代码味道,我会在纠正时尽量优雅地处理:)

我只能假设“Order”是您的 EF 实体?如果是这样,我强烈建议通过为表单创建视图模型并将数据复制到其中,将其与视图分开。您的视图模型实际上应该只包含表单将使用或操作的属性。

我还假设 orderRepository.GetOrder() 是一个从数据存储检索订单的数据层调用?

您还声明了可能未使用的变量。var order =即使您的模型无效,也会加载“ ”,并且var success =永远不会使用“”。

TryUpdateModel 和 UpdateModel 对于现实世界的编程来说并不是很健壮。老实说,我并不完全相信他们应该在那里。我通常使用更抽象的方法,例如服务/工厂模式。这是更多的工作,但给你更多的控制权。

对于您的情况,我会推荐以下模式。有最少的抽象,但它仍然为您提供比使用 TryUpdateModel / UpdateModel 更多的控制:

    public ActionResult ChangeOrder(OrderViewModel model) {
        if(ModelState.IsValid) {
            // Retrieve original order
            var order = orderRepository.GetOrder(model.OrderId);

            // Update primitive properties
            order.Property1 = model.Property1;
            order.Property2 = model.Property2;
            order.Property3 = model.Property3;
            order.Property4 = model.Property4;

            // Update collections manually
            order.Collection1 = model.Collection1.Select(x => new Collection1Item {
                Prop1 = x.Prop1,
                Prop2 = x.Prop2
            });

            try {
                // Save to repository
                orderRepository.SaveOrder(order);
            } catch (Exception ex) {
                ModelState.AddModelError("", ex.Message);
                return View(model);
            }
            return RedirectToAction("SuccessAction");
        }
        return View(model);
    }
Run Code Online (Sandbox Code Playgroud)

不太理想,但它应该可以为您提供更好的服务......

我建议你参考这篇文章,它是类似的。