使用实体框架更新导航属性

时间:2014-01-15 02:05:17

标签: c# asp.net-mvc entity-framework asp.net-web-api

我正在构建一个应用程序,以帮助举办葡萄酒之夜,客人将尝试识别更昂贵的葡萄酒。

为了简单起见,我将仅阐述两个问题:

public class Choice
{
    public int Id { get; set; }
    public virtual Event Event { get; set; }
    public virtual Wine Wine { get; set; }
    public virtual ApplicationUser User { get; set; }
    public string Guess { get; set; }
    public string Comment { get; set; }
}

public class Event
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public virtual ICollection<Wine> Wines { get; set; }
    public virtual ICollection<Choice> Choices { get; set; }
    public virtual ICollection<WineAnswer> Answers { get; set; }
}

现在,在客人猜测哪种葡萄酒更贵的视图中,我隐藏了一些字段,其中我保留了其他一些实体的唯一标识符:

 @Html.HiddenFor(event => event.Id)

现在,当客人通过Web API发布他们的选择时,模型是水合的,但模型的导航属性很贫乏:

public async Task<IHttpActionResult> PostChoice(Choice choice)
{
   /* At this point, the model looks like:
    Choice
       .Id = 0
       .Guess = "A",
       .Comment = "My comment!",
       .Event = { Event
                      .Id = 1,
                      .Name = ""
                      .Date = 01/01/0001 00:00:00
                }
}

因此,如果我尝试在Choice上执行更新,Event也会更新,但会使用其属性的默认值。不好!<​​/ p>

在我保存之前,我可以做类似的事情:

 choice.Event = db.Events.Single(e => e.Id == choice.Event.Id)

但是有一个数据库命中来获取Event的所有必要属性,然后另一个数据库不必要地使用未更改的值更新它。这似乎是一大笔开销。

有更简单,更有效的方法吗?

2 个答案:

答案 0 :(得分:2)

EventID实体添加Choice媒体资源:

public class Choice
{
    public int Id { get; set; }

    [ForeignKey("Event")]
    public int EventID { get; set; }

    public virtual Event Event { get; set; }
    public virtual Wine Wine { get; set; }
    public virtual ApplicationUser User { get; set; }
    public string Guess { get; set; }
    public string Comment { get; set; }
}

这样您就可以在EventChoice之间创建一对多关系,并且当客人猜测时,您无需保存Event导航属性。< / p>

我不确定您的模型或视图是什么样的,但使用此方法,您只需将Event实体中的事件ID分配给EventID属性即可。然后在表单中,您将拥有该属性的隐藏输入:

@Html.HiddenFor(m => m.EventID)

然后只需更新数据库中的Choice实体,而不会影响相应的Event

答案 1 :(得分:0)

在db ...

中更新模型时尝试此操作
context.Entry(Choice).State = EntityState.Modified;
context.Entry(Choice).Property(x => x.Event).IsModified = false;
context.SaveChanges();