2013-03-16 164 views
0

我試圖寫一個程序來掃描包含電視節目的文件夾目錄,查找有關使用tvrage API的節目的一些細節,然後使用實體框架的細節保存到數據庫DB。實體框架插入錯誤的實體插入的SaveChanges

我TVShow表p鍵是相同的值從tvrage數據庫顯示ID採取,並且我有當重複或類似的文件夾名稱返回相同的顯示信息的問題。在一個情況我有一個包含三個文件夾的目錄,「別名」,「別名1」,「兄弟連」我從我的代碼如下輸出

*電視節目*

別名....... NO MATCH ...... ADDING ........ DONE

別名1 ...... NO MATCH .... .ADDING .... CANT ADD,ID已存在DB

兄弟...... NO MATCH..ADDING波段的....

之前對context.SaveChanges得到一個UpdateException();行 違反PRIMARY KEY約束'PK_TVShows'。

我可以看到使用SQL事件探查器的問題是,我的應用程序試圖執行上的別名顯示插入第二次用複製的鑰匙,但我不明白爲什麼。當我在foreach循環的第二個交互(第二個「別名」文件夾)上遍歷代碼時,繞過了將show實體保存到數據庫的代碼。

它只是在foreach循環的下一次迭代時,我創建了一個新的「兄弟樂隊」TVShow實體嗎?我是否實際上到達了將Tvshow添加到上下文並保存的代碼,此時應用程序崩潰。在視覺工作室,我可以看到 在崩潰的那一點;

  • 在context.TVShows.AddObject(顯示) 「節目」 實體是 「兄弟連」 W /唯一ID
  • context.TVShows只包含一個記錄,該第一別名實體

但是,SQL事件探查器顯示的EntityFramework是不是插入別名第二次,我感到這是爲什麼

private void ScanForTVShowFolders(GenreDirectoryInfo drive) { 
     IEnumerable<DirectoryInfo> shows = drive.DirInfo.EnumerateDirectories(); 

     foreach (DirectoryInfo d in shows) { 
     //showList contains a list of existing TV show names previously queried out of DB 
      if (showList.Contains(d.Name)) { 
       System.Console.WriteLine(d.Name + ".....MATCH"); 

      } else { 
       System.Console.Write(d.Name + "......NO MATCH..ADDING...."); 
       TVShow show = LookUpShowOnline(d.Name, drive.GenreName); 

       if (show.Id == -1) { // id of -1 means online search failed 
        System.Console.Write("..........CANT FIND SHOW" + Environment.NewLine); 

       } else if (context.TVShows.Any(a => a.Id == show.Id)) { //catch duplicate primary key insert 
        System.Console.Write(".......CANT ADD, ID ALREADY EXISTS IN DB" + Environment.NewLine); 

       } else { 
        context.TVShows.AddObject(show); 
        context.SaveChanges(); 
        System.Console.Write("....DONE" + Environment.NewLine); 
       } 

      } 

     } 

     private TVShow LookUpShowOnline(string name, string genre) { 

     string xmlPath = String.Format("http://services.tvrage.com/feeds/search.php?show='{0}'", name); 

     TVShow aShow = new TVShow(); 
     aShow.Id = -1; // -1 = Can't find 

     XmlDocument xmlResp = new XmlDocument(); 
     try { xmlResp.Load(xmlPath); } catch (WebException e) { System.Console.WriteLine(e); } 

     XmlNode root = xmlResp.FirstChild; 
     if (root.NodeType == XmlNodeType.XmlDeclaration) { root = root.NextSibling; } 

     XmlNode tvShowXML; 
     //if (showXML["episode"] == null) 
     // return false; 

     tvShowXML = root["show"]; 

     if (tvShowXML != null) { 

      aShow.Id = System.Convert.ToInt16(tvShowXML["showid"].InnerText); 
      aShow.Name = tvShowXML["name"].InnerText.Trim(); 
      aShow.StartYear = tvShowXML["started"].InnerText.Trim(); 
      aShow.Status = tvShowXML["status"].InnerText.Trim(); 
      aShow.TVGenre = context.TVGenres.Where(b => b.Name.Trim() == genre).Single(); 
     } 

     return aShow; 
    } 


} 

編輯難倒做更多的閱讀我將context.ObjectStateManager添加到我的調試監視列表中,每次我創建一個新的TVShow實體時,都會向_addedEntityStore添加一條新記錄。實際上,如果我刪除context.TVShows.AddObject(顯示)代碼仍然更新數據庫,所以手動添加到上下文似乎是多餘的。

回答

0

原來context.TVShows.AddObject(顯示)是在我的情況是不必要的,我是無意中將所有創建顯示實體的背景下,當該查詢運行

aShow.TVGenre = context.TVGenres.Where(B => b.Name.Trim()== genre).Single();

這不是我想要的,我只是想創建對象,然後決定是否添加它。現在我很容易修復,我知道它爲什麼會發生。

0

如果您是通過foreach循環插入對象>更好地保持主鍵之外,並使其遞增!

例如:INT NEWID = Shows.Select(d => d.Id)。最大();

的foreach(............)
{

show.Id = newID++; 
. 
. 
. //remaining fields 
. 

context.TVShows.AddObject(顯示);

}
context.SaveChanges();

它適合我... !!