2014-02-11 56 views
0

我創建了一個MVC 5網站來跟蹤高爾夫錦標賽的結果。我有3個關鍵表,事件有很多結果高爾夫球手有很多結果。所以對於的任何一行結果表我可以鏈接到高爾夫球手和事件。帶插入關係的EF插入

我首先使用EF6代碼來堅持SQL Server。

這裏是我的事件POCO:

public class Event 
    { 
     public int EventId { get; set; } 
     public string VenueName { get; set; } 
     public string CourseName { get; set; } 
     public String FirstTeeOff { get; set; } 
     public DateTime EventDate { get; set; } 
     public decimal Fee { get; set; } 
     public virtual ICollection<Result> Results { get; set; } 
    } 

而對於高爾夫球:

public class Golfer 
    { 
     public int GolferId { get; set; } 
     public string FirstName { get; set; } 
     public string Surname { get; set; } 
     public int CurrentHandicap { get; set; } 
     public string Email { get; set; } 
     public string Telephone { get; set; } 
     public virtual ICollection<Result> Results { get; set; } 
    } 

而對於結果:

public class Result 
    { 
     public int ResultId { get; set; } 
     public Golfer Golfer { get; set; } 
     public Event Event { get; set; } 
     public bool Attendance { get; set; } 
     public int HandicapPlayed { get; set; } 
     public int ScoreCarded { get; set; } 

     public Result() 
     { 
      Event = new Event(); 
      Golfer = new Golfer(); 
     } 
    } 

這裏是我的模型方面:

public class ModelContext : IdentityDbContext<ApplicationUser>, SANDGolf.DataLayer.IModelContext 
    { 
     public ModelContext() : base("ModelContextConString") { } 

     public virtual DbSet<SANDGolf.DomainClasses.Golfer> Golfers { get; set; } 
     public virtual DbSet<SANDGolf.DomainClasses.Event> Events { get; set; } 
     public virtual DbSet<SANDGolf.DomainClasses.Result> Results { get; set; } 
    } 

我正在使用以下控制器操作嘗試插入結果表以記錄出席情況。

[HttpPost] 
     [Authorize] 
     public ActionResult ExpectedAttendance(ExpectedAttendanceViewModel eaVM) 
     { 
      try 
      { 
       foreach(GolferAttendanceViewModel gaVM in eaVM.GolferAttendanceViewModel) 
       { 
        DomainClasses.Result resultDomain = new DomainClasses.Result(); 

        resultDomain.Attendance = gaVM.Attending; 
        resultDomain.Event.EventId = eaVM.Event.EventId; 
        resultDomain.Golfer.GolferId = gaVM.Golfer.GolferId; 

        _context.Entry(resultDomain).State = EntityState.Modified; 
        _context.SaveChanges(); 
       } 

       return RedirectToAction("Index"); 
      } 
      catch 
      { 
       return View(); 
      } 
     } 

當行_context.SaveChanges();執行我得到以下錯誤:

存儲更新,插入或刪除語句影響意外數量的行(0)。自實體加載後,實體可能已被修改或刪除。刷新ObjectStateManager條目。

我是新來的EF,所以如果有人能讓我知道我哪裏出錯了,我會很感激。

+0

爲什麼你不只是調用_context.Results.Add(resultDomain)並保存更改的任何特定原因? –

回答

1

我建議切換到外鍵關聯。例如:

public virtual Golfer Golfer {get;set;} 

將變爲:

public int GolferId {get;set;} 
public virtual Golfer Golfer {get;set;} 

使用這種方法,你可以直接設置,例如:

Golfer myGolfer = getGolferById(1); // or gaVM.Golfer.GolverId; 
Result.GolferId = myGolfer.GolferId; 

你可以閱讀更多有關這對my blog

並增加一個新的實體數據庫的時候,你不應該使用:

_context.Entry(resultDomain).State = EntityState.Modified; 

但使用@ danludwig的解決方案。

+0

我今天重新訪問了這個項目,進行了進一步的修改。我發現Marthijn的建議非常有幫助。這由O'Reilly編程實體框架Code First的第4章予以備份,其中說明了「這對外國主要屬性來說更容易」 –

+0

是的,這很容易。 – danludwig

1

導航屬性也需要是虛擬的。

public virtual Golfer Golfer { get; set; } 
public virtual Event Event { get; set; } 

此外,像斯科特·科比特說,新的實體不應該修改狀態,而是增加狀態:

_context.Entry(resultDomain).State = EntityState.Added; 

...或者更好的是:

_context.Results.Add(resultDomain); 
+0

如果我想更新結果記錄,我應該仍然使用Add方法嗎?對不起,我不會有機會嘗試這個,直到今天晚上 –

+0

不。您使用添加插入。如果你想更新,你可以將狀態改爲修改,就像你的問題一樣。 – danludwig

+0

它工作!感謝danludwig和Scott。我想我讓EF爲我做這件事很麻煩。我很習慣插入孩子,獲得外鍵,然後插入父母 –