2014-02-26 25 views
1

我有以下類(我只是顯示出重要的屬性):實體框架多對多清單表協會

public class TypeLocation 
{ 
    [Key] 
    public int Id {get; set;} 
    public string Country {get; set;} 
    public string State {get; set;} 
    public string County {get; set;} 
    public string City {get; set;} 

    public List<Offer> Offers {get; set; } 
    public TypeLocation() 
    { 
     this.Offers = new List<Offer>(); 
    } 
} 

public class Offer 
{ 
    public int Id { get; set; } 

    public ICollection<TypeLocation> LocationsToPublish { get; set; } 
} 

這會在數據庫中的以下內容:

Database Schema

我的問題/問題

TypeLocations表是prepop用國家/州/縣/城市記錄的靜態列表,其中一個或多個可以與LocationsToPublish財產中的要約相關聯。當我嘗試使用以下代碼添加位置時,實體框架在TypeLocation表中添加了一條NEW記錄,然後通過在OfferTypeLocations表中添加記錄來創建關聯。

public static bool AddPublishLocation(int id, List<TypeLocation> locations) 
    { 
     try 
     { 
      using (AppDbContext db = new AppDbContext()) 
      { 
       Offer Offer = db.Offers 
        .Include("LocationsToPublish") 
        .Where(u => u.Id == id) 
        .FirstOrDefault<Offer>(); 

       //Add new locations 
       foreach (TypeLocation loc in locations) 
       { 
        Offer.LocationsToPublish.Add(loc); 
       } 
       db.SaveChanges(); 
      } 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

我不想要一個新的記錄添加到TypeLocations表,只是一個關係記錄創建在OfferTypeLocations表的關聯。有什麼想法我做錯了什麼?

解決方案

感謝@Mick誰低於說,我已經找到了解決辦法。

public static bool AddPublishLocation(int id, List<TypeLocation> locations) 
    { 
     try 
     { 
      using (AppDbContext db = new AppDbContext()) 
      { 
       Offer Offer = db.Offers 
        .Include("LocationsToPublish") 
        .Where(u => u.Id == id) 
        .FirstOrDefault<Offer>(); 

       //Add new locations 
       foreach (TypeLocation loc in locations) 
       { 
        //SOLUTION 
        TypeLocation ExistingLoc = db.AppLocations.Where(l => l.Id == loc.Id).FirstOrDefault<TypeLocation>(); 

        Offer.LocationsToPublish.Add(loc); 
       } 
       db.SaveChanges(); 
      } 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

會發生什麼事是,利用現有的AppDbContext,我檢索來自TypeLocations表中的現有記錄(在這裏確定爲AppLocations),然後將它添加到LocationsToPublish實體。

關鍵是我將使用當前的AppDbContext(用Using()語句包裝)進行所有工作。這個上下文之外的任何數據都是純粹的信息性的,用於幫助在AppDbContext上下文中進行記錄查找或創建。我希望這是有道理的。

+0

如果打開探查,你會看到這個解決方案產生額外查詢每個位置添加。它會工作,但是它會比下面的解決方案慢很多。 – Mick

+0

List 實際上是從網頁中的數據發佈生成的,所以沒有任何上下文可以傳入。實際上,我們不應該在任何時間點傳入太多的TypeLocations,最大可能爲10-15。 – FrankO

回答

0

TypeLocations正在從不同的AppDbContext加載,它們被視爲您正在構建的AppDbContext中的新實體。修復:

  1. 假設位置是從AppDbContext的實例之外分解出來的,您可以將這些實體附加到新的上下文中。 或
  2. 傳入用於將位置加載到您的AddPublishLocation方法中的AppDbContext。

我會選擇2: -

public static bool AddPublishLocation(AppDbContext db, int id, List<TypeLocation> locations) 
{ 
    try 
    { 
     Offer Offer = db.Offers 
      .Include("LocationsToPublish") 
      .Where(u => u.Id == id) 
      .FirstOrDefault<Offer>(); 

     //Add new locations 
     foreach (TypeLocation loc in locations) 
     { 
      Offer.LocationsToPublish.Add(loc); 
     } 
     db.SaveChanges(); 
     return true; 
    } 
    catch 
    { 
     return false; 
    } 
} 
+0

我不明白他們是如何從不同的AppDbContext加載的。你有更多關於這方面的信息嗎? – FrankO

+0

我想到了你的答案,並找到了解決方案!基本上,我需要從匹配我嘗試添加的位置ID的表中檢索現有TypeLocation記錄。我更新了我的問題。 – FrankO

+0

每次您實例化一個新的AppDbContext時,實例都會跟蹤通過上下文加載的所有實體,而未通過AppDbContext實例加載的實體在添加到上下文時會被視爲新實體。您的原始代碼清楚地傳遞到TypeLocations中,該TypeLocations必須使用AppDbContext的其他實例加載到別處。爲了將實體視爲現有實體,需要通過您的方法中的AppDbContext附加或加載實體,這就是您的解決方案起作用的原因 – Mick