简体   繁体   English

实体框架-保存子实体

[英]Entity Framework - Saving child entities

I'm using EF and WebAPI and trying to save a new object that has many child properties (eg city, country, etc). 我正在使用EF和WebAPI,并试图保存一个具有许多子属性(例如城市,国家等)的新对象。 The data for these properties is pulled from an external source but I want to save them to my database along with my object for reporting purposes. 这些属性的数据是从外部来源提取的,但是我想将它们与对象一起保存到数据库中以进行报告。 For that reason I need to first check if the new child being passed along with the new parent already exists (remember, it's not being pulled from my database). 出于这个原因,我需要首先检查与新父级一起传递的新子级是否已经存在(请记住,它不是从数据库中提取的)。

If I've selected, for example, a city I've already saved, it saves a duplicate row because the object passed in doesn't have MY city ID so EF thinks it's a new item. 例如,如果我选择了一个已经保存的城市,它会保存重复的行,因为传入的对象没有我的城市ID,因此EF认为这是一个新项目。

I've tried attaching if it is already in the DB but it won't let me attach. 我已经尝试附加数据库中的附加文件,但不允许我附加。 It says the item is already being tracked by the context. 它说该项目已经被上下文跟踪。

Here is my code for trying to check and save one of the child collections before saving the new parent. 这是我的代码,用于在保存新的父代之前尝试检查并保存其中一个子代集合。

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);
     }                 
}

I need to grab the ID of the existing entity from my context but after that I can't attach and let EF know that it doesn't need to create a new entry for this item. 我需要从上下文中获取现有实体的ID,但是此后,我将无法附加,并让EF知道它不需要为此项目创建新条目。

I'm pretty new to EF and I'm constantly struggling with saving / updating any entities that have child collections. 我对EF来说还很陌生,我一直在努力保存/更新任何具有子集合的实体。 I can't seem to wrap my mind around when things are attached to the context and when not etc. 当事物附加到上下文时以及何时不附加时,我似乎无法全神贯注。

Don't try to set the Id, just create a new list with the existing country entities (and make as few queries as possible): 不要尝试设置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;

This is probably not the very best way to do this, but it's the first one I could think of. 这可能不是执行此操作的最佳方法,但这是我想到的第一个方法。

Assuming a unique constraint on the country_code column doesn't fix the problem attaching the entity. 假设country_code列上的唯一约束不能解决附加实体的问题。 I'd try this... 我会尝试这个...

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);

Or even simpler, just assign the values on existingCountry from Country. 甚至更简单,只需在Country的现存Country中分配值即可。 In my little universe I'd code generate a solution for this using T4 templates... 在我的小宇宙中,我将使用T4模板为此代码生成解决方案...

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM