无法更新实体框架模型

时间:2014-01-13 10:01:13

标签: c# entity-framework asp.net-mvc-4 ef-database-first

我花了将近七个小时来解决这个问题,但无法提出解决方案。我就是这样,与你分享这个问题。

请注意,以下示例是我原始项目的简化和子集。我尽可能地为你简化它。

首先,我有两种商业模式:

enter image description here

以下EDMX图如下:

EDMX Diagram

我正在使用MVC 4,我有一个简单的页面,你可以分别输入主队和客队名称,还有一个保存按钮来保存这些球队和比赛:

New match entry page

CSHTML

@model TestEF.Data.Match
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>NewMatch</title>
</head>
<body>
    <div>
        Status: @ViewBag.Status
    </div>
    <div id="NewMatchFormContainer">
        @using (Ajax.BeginForm(new AjaxOptions() { Url = "/Match/NewMatch", UpdateTargetId = "NewMatchFormContainer" }))
        {
            @Html.ValidationSummary(false)

            @Html.TextBox("HomeTeamName", "", new { Name = "HomeTeam.TeamName" });
            @Html.TextBox("AwayTeamName", "", new { Name = "AwayTeam.TeamName" });

            <input type="submit" value="Save" />
        }
    </div>
</body>
</html>

控制器

public class MatchController : Controller
{
    TestEFEntities _dbContext = new TestEFEntities();

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult NewMatch()
    {
        return View();
    }

    [HttpPost]
    public ActionResult NewMatch(Match matchData)
    {
        try
        {
            if (ModelState.IsValid)
            {
                using (TransactionScope ts = new TransactionScope())
                {
                    string homeTeamName = matchData.HomeTeam.TeamName;
                    Team existingHomeTeam = _dbContext.Teams.SingleOrDefault(i => i.TeamName == homeTeamName);
                    Team homeTeam = existingHomeTeam ?? matchData.HomeTeam;
                    homeTeam.UpdatedDate = DateTime.Now;

                    if (existingHomeTeam == null)
                    {
                        _dbContext.AddToTeams(homeTeam);
                    }
                    else
                    {
                        _dbContext.ObjectStateManager.ChangeObjectState(homeTeam, System.Data.EntityState.Modified);
                    }

                    string awayTeamName = matchData.AwayTeam.TeamName;
                    Team existingAwayTeam = _dbContext.Teams.SingleOrDefault(i => i.TeamName == awayTeamName);
                    Team awayTeam = existingAwayTeam ?? matchData.AwayTeam;
                    awayTeam.UpdatedDate = DateTime.Now;

                    if (existingAwayTeam == null)
                    {
                        _dbContext.AddToTeams(awayTeam);
                    }
                    else
                    {
                        _dbContext.ObjectStateManager.ChangeObjectState(awayTeam, System.Data.EntityState.Modified);
                    }

                    matchData.HomeTeam = homeTeam;
                    matchData.AwayTeam = awayTeam;

                    _dbContext.AddToMatches(matchData);
                    _dbContext.SaveChanges();

                    ts.Complete();
                }

                ViewBag.Status = "Success";

                return PartialView(matchData);
            }
            else
            {
                ViewBag.Status = "Invalid input.";

                return PartialView(matchData);
            }
        }
        catch (Exception ex)
        {
            ViewBag.Status = "Error: " + (ex.InnerException != null ? ex.InnerException.Message : ex.Message);

            return PartialView(matchData);
        }
    }
}

正如您在控制器内部所看到的,输入的团队名称将与数据库中的名称进行比较。如果存在,则更新;其他插入。插入没有问题但是当在文本框中输入现有团队名称时,我收到以下错误消息:

  

无法将值NULL插入列'UpdatedDate',表中   'TestEF.dbo.Teams';列不允许空值。 INSERT失败。该   声明已被终止。

即使在控制器内部,我也会收到此错误,我明确地为需要更新的记录设置UpdateDate并将其状态设置为Modified。但是,错误消息显示如果未设置UpdateDate字段。我调试并确保字段正确更新但在SQL Profiler中没有设置UpdateDate。我很困惑。

如果需要,我可以分享完整的源代码。

更新我怀疑它与Attach / Detach有关,但我不确定。

更新2 我已经简化了代码,看它是否有效。那为什么原始代码不起作用?

Team homeTeam = new Team() { TeamId = 1 };
Team awayTeam = new Team() { TeamId = 2 };

_dbContext.Teams.Attach(homeTeam);
homeTeam.UpdatedDate = DateTime.Now;

_dbContext.Teams.Attach(awayTeam);
awayTeam.UpdatedDate = DateTime.Now;

Match newMatch = new Match()
{
    HomeTeam = homeTeam,
    AwayTeam = awayTeam,
    UpdateDate = DateTime.Now
};

_dbContext.AddToMatches(newMatch);
_dbContext.SaveChanges();

3 个答案:

答案 0 :(得分:0)

UpdatedDate不允许空值。使其成为数据库中可以为空的列。

在你的EDMX中也作为评论中提到的scheien。

答案 1 :(得分:0)

您在EF中的架构表示在添加/插入或更新时不允许输入Null值。

确保传递正确的不可为空的值。 您还可以更改表的架构并更新模型,以便输入null。

答案 2 :(得分:0)

在此处设置断点:awayTeam.UpdatedDate = DateTime.Now;

然后当你运行它时,你可以判断它是否指向现有团队。

我很确定问题出在您尝试进行更新时。在这种情况下,您没有分离原始对象,而是尝试重新分配。尝试分离您的existingAwayTeam,然后附加您的matchData.AwayTeam,将其标记为已修改,并尝试保存它。