0

我试图更新模型,但得到错误“操作失败:关系无法更改,因为一个或多个外键属性是不可空。当对关系进行更改时,相关的外键属性设置为空值;如果外键不支持空值,则必须定义新的关系,必须为外键属性指定另一个非空值,或者不相关的对象必须被删除。“外键约束,与收集子对象的EF

从我从The relationship could not be changed because one or more of the foreign-key properties is non-nullable明白这个问题可能是与实体框架是如何处理我的虚拟ICollection的

但是我真的不知道如何使用脚手架库模式时,实施解决方案。我必须编辑Save() - 方法ParentObjectRepository类吗?

其实我真的觉得必须有一些方法让EF明白这一点。我看不出EF团队是怎么想“可能没有人使用具有外键约束的对象集合,不支持”。

更新 添加代码

[HttpPost] 
public ActionResult Edit(int id, FormCollection formCollection) 
{ 
    var eventRepository = new MagnetEventRepository(); 
    var original = eventRepository.Find(id); 
    UpdateModel(original); 
    eventRepository.Save(); 
    return RedirectToAction("Details", "Home", new { slug = original.Slug }); 
} 

public void Save() 
{ 
    context.SaveChanges(); 
} 

更多代码:

public class MagnetEvent 
{ 
    public virtual int Id { get; set; } 

    [Required] 
    public virtual string Name { get; set; } 

    [Required] 
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm}")] 
    [DataType(DataType.DateTime)] 
    public virtual DateTime? StartDate { get; set; } 

    public virtual string Description { get; set; } 

    [StringLength(100)] 
    public virtual string Slug { get; set; } 

    public virtual int MaximumCapacity { get; set; } 

    [DataType(DataType.Currency)] 
    public virtual int TicketPrice { get; set; } 

    public virtual int LocationId { get; set; } 
    public virtual Location Location { get; set; } 

    public virtual Collection<Ticket> Tickets { get; set; } 

    public virtual Collection<AttendeeInformationField> CaptureAttendeeInformationFields { get; set; } 

    public virtual int CustomerId { get; set; } 

    [Required] 
    public virtual CUSTOMER Customer { get; set; } 
} 

的保存() - 方法是从MagnetEventRepository,它是从上述的类脚手架。

另一个更新 我通过将AttendeeInformationField中的MagnetEventId更改为可为null来成功地删除错误。在检查数据库时,我可以看到确切的问题。

比方说,我有一个值为“电子邮件”的AttendeeInformationField。当我编辑我的MagnetEvent时,AttendeeInformationField将MagnetEventId更新为null,然后使用正确的MagnetEventId和Value添加新帖子。

我非常希望AttendeeInformationField中的帖子被更新。

+0

你能发布你的查询和更新代码吗? – 2012-04-16 07:23:56

+0

当然,我更新了原文。 – 2012-04-16 07:49:03

回答

0

我找到了解决我的问题的方法。当涉及到UpdateModel和包含ICollection的模型时,它似乎是ASP.NET MVC中的一个错误(?)。

的解决方案是覆盖默认行为,因为在这个博客帖子描述:http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx

更新 我找到了解决办法!以上仅适用于更新集合中的现有项目。为了解决这个问题,我必须手动检查并添加新的AttendeeInformationFields。像这样:

[HttpPost] 
public ActionResult Edit(int id, MagnetEvent magnetEvent) 
{ 
    var eventRepository = new MagnetEventRepository(); 
    var original = eventRepository.Find(id); 
    UpdateModel(original); 
    foreach (var attendeeInformationField in magnetEvent.CaptureAttendeeInformationFields) 
    { 
     var attendeeInformationFieldId = attendeeInformationField.Id; 
     if (original.CaptureAttendeeInformationFields.AsQueryable().Where(ai => ai.Id == attendeeInformationFieldId).Count() == 0) 
     { 
      original.CaptureAttendeeInformationFields.Add(attendeeInformationField); 
     } 
    } 
    eventRepository.Save(); 
} 

与修改的DefaultModelBinder一起,这实际上同时适用于编辑和添加。目前我还没有试过删除。

不过,我希望有一个更简单的方法来做到这一点。看起来像很多编码来完成一项非常基本的任务。

0

您可以添加事件对象的代码吗?你称之为原创者。

它可能会使UpdateModel更改关联对象的某些信息,如果是这样,那也不好。不知道这个,虽然我看不到所有的代码。

我更喜欢不使用UptadeModel,而是使用inputmodel或MVC模型作为参数,并手动将chages映射到加载的原始对象。

Antoher问题是,我看不到如果 eventRepository.Save();

真的做了SaveShages?可以?我可以在另一种方法中选择一些上下文代码保存?

+0

我更新了我原来的帖子。 – 2012-04-16 08:10:31

0

作为例外说,它像你的关联集合或其他关联对象的接缝不能找到有效的ID值。

您是否急于加载关联的对象?像客户?

+0

据我所知,虚拟意味着渴望加载,所以是的! 从那篇文章我链接到我认为它与我的ICollection有关 调试时,一切看起来不错,但保存失败 – 2012-04-16 08:22:07

+0

虚拟意味着它可以延迟加载,如果打开。 Eagerload是你说它应该包含关联的时候。 如果你调试了查找(...)会给你一个在id和关联中没有空值的clss? – RockJohan 2012-04-16 08:27:53

+0

对不起,我的坏。我有延迟加载。当我调试时,我可以看到所有的值。 – 2012-04-16 08:32:23

0

有一点值得注意的是,根据您的FK不可空的事实推断,您不应该对客户有[必需的]。如果模型中没有FK,则只能在导航属性上使用该属性。

要尝试诊断问题,您可以加载对象并在调试器中查看它,您应该期望locationId和CustomerId都具有非零值。

+0

是的,调试时,LocationId和CustomerId都具有正确的值。一切运行良好,直到我试图实现ICollection 2012-04-16 11:39:12

+0

我增加了更多的信息,原来的文章 – 2012-04-16 12:24:56