2013-12-15 57 views
0

我使用EF和WebAPI並試圖保存具有許多子屬性(例如城市,國家等)的新對象。這些屬性的數據是從外部源獲取的,但我想將它們與我的對象一起保存到數據庫中以用於報告目的。出於這個原因,我需要首先檢查是否新父項與新父項一起存在(請記住,它不會從我的數據庫中提取)。實體框架 - 保存子實體

如果我選擇了一個我已經保存的城市,它會保存一個重複的行,因爲傳入的對象沒有我的城市ID,所以EF認爲這是一個新項目。

我已經試過如果它已經在數據庫中,但它不會讓我附上。它表示該項目已被上下文跟蹤。

這是我的代碼,用於在保存新父項之前檢查並保存其中一個子集合。

foreach (HBCountry country in hbcampaign.HBTargetingSpec.HBCountries) 
{ 
    if (db.HBCountries.Any(c => c.country_code == country.country_code)) 
    { 
     country.CountryID = db.HBCountries.Where(c => c.country_code == country.country_code) 
              .FirstOrDefault() 
              .CountryID; 
     db.HBCountries.Attach(country); 
    } 
    else 
    { 
     db.HBCountries.Add(country); 
    }     
} 

我需要抓住從我的背景下,現有實體的ID,但在那之後我不能附上,讓EF知道,它並不需要爲這個項目的新條目。

我對EF很新,我一直在努力保存/更新任何具有子集合的實體。我似乎無法將我的想法包括在附加到上下文時以及什麼時候沒有。

+0

你已經安裝跟蹤實體。只需獲取父項並使用parent.Childern.Add()或parent.ChildernId = id添加子實體。我希望你不要在這裏使用Lazy Loading。 –

+0

最好使用'Any()'而不是'Count()> 0'。 'Count()'遍歷整個集合,沒有謂詞的Any()'只是查看第一個項目並返回。 –

+0

謝謝。我更新了我的代碼以使用Any()。我仍然堅持。如果我從我自己的數據源中提取子屬性,這不會是一個大問題,但是因爲我基本上每次都發送一個「新」項目(即,它沒有來自我的數據庫的ID) 。對不起,如果這非常愚蠢。我真的很難與EF握手。 – GooseZA

回答

0

不要嘗試設置Id,只需使用現有的國家實體創建新列表(並儘可能少地查詢儘可能):

var newList = new List<HBCountry>(); 
foreach (HBCountry country in hbcampaign.HBTargetingSpec.HBCountries) 
{ 
    var countryMatch = db.HBCountries.FirstOrDefault(c => c.country_code == country.country_code) 
    if (countryMatch != null) 
    { 
     newList.Add(countryMatch); 
    } 
    else 
    { 
     newList.Add(country); 
    }     
} 

hbcampaign.HBTargetingSpec.HBCountries = newList; 

這可能不是最好的方式來做到這一點,但它是我能想到的第一個。

+0

嗨,感謝您的回覆。我早些時候嘗試過。在這種情況下,它不能分配給國家,因爲它是一個foreach迭代變量。 – GooseZA

+0

啊,當然。我的錯。編輯答案。 –

+0

這個伎倆!非常感謝。正如你所說,可能不是最好的辦法,但它的工作原理,我沒有時間。再次感謝=) – GooseZA

0

假設country_code列上的唯一約束不能解決附加實體的問題。我想試試這個...

var countryCodes = hbcampaign.HBTargetingSpec.HBCountries.Select(c => country.country_code); 
// Gives you the list of existing countries in one SQL query 
var existingCountries = db.HBCountries.Where(c => 
    countryCodes.Contains(c.country_code); 

foreach (HBCountry country in existingCountries) 
{ 
    var existingCountry = hbcampaign.HBTargetingSpec.HBCountries.FirstOrDefault(c => c.country_code == country.country_code); 
    existingCountry.CountryID = country.CountryID; 
    db.HBCountries.Detach(country); 
    db.HBCountries.Attach(existingCountry); 
} 

var newCountries = hbcampaign.HBTargetingSpec.HBCountries.Where(c => !existingCountries.Any(c2 => c2.country_code == c.country_code); 
foreach (HBCountry country in newCountries) 
    db.HBCountries.Add(country); 

或者更簡單一些,只需在Country中指定existingCountry上的值即可。在我的小宇宙我的代碼生成此使用T4模板的解決方案......

http://msdn.microsoft.com/en-us/data/gg558520.aspx