2013-03-16 166 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();

它适合我... !!