0

背景:我正在解析XML文件(書籤事件信息),然後嘗試通過實體框架代碼優先創建基於解析數據的數據庫記錄(在Entity Framework Power Tools Beta 3的幫助下)。無法讓我的實體尊重域的引用完整性

排序解析邏輯後,我對解析後的數據存儲到數據庫中的以下代碼:

using (var context = new BSContext()) 
{ 
    foreach (var e in events) 
    { 
     try 
     {      
      // Create the Author Entity 
      var AuthorEntity = parser.getAuthorByName(e.Author); 
      if (AuthorEntity == null) 
      { 
       AuthorEntity = new Author() 
       { 
        Name = e.Author 
       }; 
       context.Authors.Add(AuthorEntity); 
       context.SaveChanges(); 
      }       


      // Create the Location Entity 
      var LocationEntity = parser.getLocationByNameAddressAndPostCode(e.Location.Name, e.Location.Address, e.Location.PostCode); 
      if (LocationEntity == null) 
      { 
       LocationEntity = new Location() 
       { 
        Name = e.Location.Name, 
        Address = e.Location.Address, 
        City = e.Location.City, 
        County = e.Location.County, 
        PostCode = e.Location.PostCode, 
        Telephone = e.Location.Telephone 
       }; 
       context.Locations.Add(LocationEntity); 
       context.SaveChanges(); 
      }       


      // Create the Book Entity 
      var BookEntity = parser.getBookByName(e.Book.Name); 
      if(BookEntity == null) 
      { 
       BookEntity = new Book() 
       { 
        Name = e.Book.Name, 
        BookImgUrl = e.Book.BookImgUrl 
       }; 
       context.Books.Add(BookEntity); 
       context.SaveChanges(); 
      } 


      // Create the Event Entity 
      string dtObjFormat = "dd MMM yyyy HH:mm"; 
      DateTime dt; 
      var EventEntity = new Event() 
      { 
       Author = AuthorEntity, 
       Book = BookEntity, 
       Info = e.Info, 
       Start = DateTime.TryParseExact(e.Date + " " + e.Time, dtObjFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt) ? dt : new DateTime(), 
       Location = LocationEntity 
      }; 
      context.Events.Add(EventEntity); 
      context.SaveChanges(); 
     } 
     catch 
     { 
      Console.WriteLine("Something went wrong!"); 
     } 
    } 
    Console.WriteLine("Looped through all Events"); 
} 

上面的代碼,試圖創建實體並將它們保存到數據庫中。當需要時,重新使用保存的實體。

所以舉例來說,在我的XML文件,作者出現了兩次,但我不希望爲作者創造兩項紀錄,因爲我已經創建了一個以前的循環爲同一作者的記錄。即使在我看來,我有代碼來處理這個(見上面),它仍然由於某種原因創建了多個作者記錄。與書籍也有同樣的問題。

getAuthorByName(String authorName)方法有以下代碼:

/// <summary> 
/// A method to get an Author Entity by name. If no Author exists, then 
/// NULL is returned. If two authors exist with the exact same name, 
/// then the first encountered is returned. 
/// </summary> 
/// <param name="authorName">The name of the Author.</param> 
/// <returns>The Author Entity</returns> 
public Author getAuthorByName(String authorName) 
{ 
    using (var context = new BSContext()) 
    { 
     return context.Authors.FirstOrDefault(x => x.Name == authorName); 
    } 
} 

兩個其它方法getBookByName(String bookName)getLocationByNameAddressAndPostCode(String lName, String lAddress, String lPostCode)都具有類似的邏輯與上述方法。

問題:停止數據庫中實體Book和Author的記錄重複。

回答

1

你應該注意的是,你有2個活動的BSContext對象被使用。實體跟蹤分別發生在每個這些上下文中。又名作者將生活在一個,而不是兩個,除非你在兩個內查詢它。

完成getAuthorByName方法後,Author實體將從任何實體上下文中分離出來。你需要做的是將這個實體重新連接到外部上下文(也就是最上面的代碼示例中的那個)。如果你不這樣做,就像在上面的代碼中一樣,BSContext並不知道它是一個現有的實體,並且認爲它是一個新實體。導致將新的作者插入到數據庫中。

或者你可以嘗試這樣做。

/// <summary> 
/// A method to get an Author Entity by name. If no Author exists, then 
/// NULL is returned. If two authors exist with the exact same name, 
/// then the first encountered is returned. 
/// </summary> 
/// <param name="authorName">The name of the Author.</param> 
/// <returns>The Author Entity</returns> 
public Author getAuthorByName(BSContext context, String authorName) 
{ 
     return context.Authors.FirstOrDefault(x => x.Name == authorName); 
} 

然後調用解析器像

var AuthorEntity = parser.getAuthorByName(context, e.Author); 
+0

製作精良點。我完全忘記了這一點。謝謝Alistair,它現在可以工作。^_ ^ – Ciwan