【问题标题】:Migrating from Model First to Code First, some breaking changes从模型优先迁移到代码优先,一些重大变化
【发布时间】:2011-07-04 16:21:54
【问题描述】:

当我使用模型优先方法时,此代码运行良好。如果是new Vote(),则停止保存投票。我猜模型首先生成的类在属性设置器上使用了一些“魔法”,我认为这就是我们将virtual 放在代码优先属性中的原因。有没有办法让它以旧的方式工作?还是应该以其他方式搜索和替换并将新对象绑定到图形?

public ActionResult Vote(int id, string votetype)
{
    int userid = ViewBag.User.Id;
    var pub = DB.Publications.Single(p => p.Id == id);
    var votes = pub.Votes.SingleOrDefault(v => v.MemberId == userid) ??
                new Vote
                {
                     MemberId = userid,
                     Publication = pub
                 };
    DB.SaveChanges();
    return RedirectToAction("Full", new { id = id });
}

【问题讨论】:

  • 这段代码应该做什么?特别是为什么SaveChanges?您只需从数据库中查询实体,但不会更改任何内容,也不会将新实体添加到上下文中。

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


【解决方案1】:

它以前有效,但从一开始就以一种糟糕的方式编写,因为它确实使用了一些内部魔法,在您的示例中它可以称为副作用。您应该避免通过副作用执行某些逻辑的代码。

神奇的是自动修复导航属性。您创建一个新的Vote 并设置其Publication 导航属性,并将Publication 实例附加到上下文。在这种情况下,EF 将为您修复关系,并且它在内部还将Vote 添加到Publication。由于修复,新的Vote 也将被跟踪(作为一个新实体)。

您在代码中首先使用的自定义类没有修复方法,除非您手动编写它或从模型和数据库中使用的 POCO T4 模板生成的代码中复制它们。如果不进行修复,新的Vote 将不会添加到上下文中,SaveChanges 将不会执行任何修改。

使用@Diego 的代码来修复您的方法。

【讨论】:

  • 很好的解释。在代码优先之前我没有使用过 EF,也不知道修复魔法。
  • @Diego:如果是 POCO,它将为您生成一个代码模板,它会导致很多问题,尤其是与延迟加载结合使用时,因为修复可能会触发对面导航属性的延迟加载。
【解决方案2】:

您在该代码中没有任何地方告诉 EF 坚持新投票。

将您获得/创建投票的行更改为:

var vote = pub.Votes.SingleOrDefault(v => v.MemberId == userid);
if (vote == null)
    pub.Votes.Add(new Vote
                  {
                      MemberId = userid,
                      Publication = pub
                  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多