我花了將近7個小時來弄明白這一點,並不能提出解決方案。所以,我在這裏,與你分享這個問題。無法更新實體框架模型
請注意,以下示例是我原始項目的簡化和子集。我儘可能爲你簡化它。
開始,我有兩種商業模式:
下EDMX圖如下:
我使用MVC 4,我有一個簡單的頁面您可以分別輸入主客場球隊名稱和保存按鈕以保存這些球隊和比賽:
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對於需要進行更新,並設置其狀態修改的記錄此錯誤。但是,錯誤消息說,如果UpdateDate字段未設置。我調試並確保字段更新正確,但在SQL事件探查器UpdateDate未設置。我很困擾。
如果需要,我可以共享完整的源代碼。
UPDATE我懷疑它與Attach/Detach有關係,但我不確定。
UPDATE 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();
您是否嘗試設置'xxx.UpdatedDate = DateTime.Now;裏面的''else' ** **後做'_dbContext.ObjectStateManager.ChangeObjectState ...'聲明?那麼,如果更新,重新設置它?試試看看它是否能解決你的問題。如果它工作讓我知道,我會發布答案。 – Belogix
我可以看看你的模特嗎? –
@Belogix,讓我試試看,我會盡快回復。 –