2014-01-13 223 views
0

我花了將近7個小時來弄明白這一點,並不能提出解決方案。所以,我在這裏,與你分享這個問題。無法更新實體框架模型

請注意,以下示例是我原始項目的簡化和子集。我儘可能爲你簡化它。

開始,我有兩種商業模式:

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對於需要進行更新,並設置其狀態修改的記錄此錯誤。但是,錯誤消息說,如果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(); 
+0

您是否嘗試設置'xxx.UpdatedDate = DateTime.Now;裏面的''else' ** **後做'_dbContext.ObjectStateManager.ChangeObjectState ...'聲明?那麼,如果更新,重新設置它?試試看看它是否能解決你的問題。如果它工作讓我知道,我會發布答案。 – Belogix

+0

我可以看看你的模特嗎? –

+0

@Belogix,讓我試試看,我會盡快回復。 –

回答

0

UpdatedDate不允許空值。將其設置爲數據庫中的空列。

而且還在您的EDMX中作爲方案在評論中提到。

+0

他也應該讓它在模型中可以爲空,以反映數據庫。 – scheien

+1

UpdateDate不是有意爲空的字段。它被設置爲插入和更新記錄。 –

+0

您編輯了代碼。如果它不是空的,你以前的版本會出錯。現在它應該可以正常工作。 –

0

EF中的模式表示在添加/插入或更新時不允許輸入空值。

請確保您傳遞了正確的非空值。 您也可以更改表格的模式並更新模型,以便輸入null。

+0

我傳遞DateTime.Now這是一個不可爲空的值。 –

0

在這裏設置一個斷點:awayTeam.UpdatedDate = DateTime.Now;

然後,當你運行它,你可以,如果它指向現有的團隊或說不清。

我敢肯定,問題是,當你試圖做一個更新。在這種情況下,您尚未分離出原始對象,而是嘗試重新分配。嘗試分離您的existingAwayTeam,然後附加您的matchData.AwayTeam,將其標記爲已修改,然後嘗試保存它。

+0

是的,只有在嘗試更新時纔會出現此錯誤,這非常令人沮喪。我將您的解決方案應用於客場球隊和主隊,現在我得到這個錯誤:「ObjectStateManager中已存在具有相同鍵的對象,ObjectStateManager無法使用同一個鍵跟蹤多個對象。」儘管我分離了現有的實體。有關進一步調查,請查看問題的** UPDATE 2 **部分。 –