2016-05-06 36 views
0

假設我正在從Excel文件中讀取數據,並且需要使用EF保存該數據。讀完excel之後,我在EF模型中構造了一個類型的實體 - 比如說假日。通過實體框架保存顯式實體

可能是這個特定的假期已經存在於我的數據庫中,或者可能不存在。我無法通過閱讀Excel文件來了解它。因此,我檢查該實體是否存在,如果是這樣,我必須修改現有實體或添加一個新實體。

以下是我如何處理邏輯。

foreach (var holiday in clientDataObj.Holidays) 
{ 
    // to check for existing holidays, no need to consider the location, as all holidays will anyway exist at root level. 
    Holiday existingHoliday = 
       ClientContext.Holidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date)); 

    if (existingHoliday == null) 
    { 
     rootLocation.Holidays.Add(holiday); 
    } 
    else 
    { 
     holiday.HolidayId = existingHoliday.HolidayId; 
     ClientContext.Entry(existingHoliday).State = System.Data.Entity.EntityState.Detached; 
     ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Modified; 
    } 
} 

ClientContext.SaveChanges(); 

我還沒有運行代碼,看它是否工作。有人可以告訴我們這是否是這樣做的方法,或者是否有解決這個問題的其他最佳做法。

回答

1

不,那不行。分離一個實體並不會刪除它,它只是從上下文的跟蹤中分離出來。

您需要將其刪除,並添加新的:同樣

ClientContext.Entry(existingHoliday).State = EntityState.Deleted; 
ClientContext.Entry(holiday).State = EntityState.Added; 

,在事件有以Excel文件中的兩個相同的假期,你可以通過你已經增加了一個,所以你需要檢查。拆,這裏將工作,因爲你已經不叫SaveChanges卻又如此的實體不在數據庫中尚未:

if(ClientContext.Entry(existingHoliday).State == EntityState.Added) 
    ClientContext.Entry(existingHoliday).State == EntityState.Detached; 

我不知道你爲什麼將它們添加到rootLocation當他們不存在的數據庫,你應該將它們添加到背景下,如果我按照你的邏輯,所以你可能有這樣的循環:

foreach (var holiday in clientDataObj.Holidays) 
{ 
    Holiday existingHoliday = 
       ClientContext.Holidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date)); 
    if (existingHoliday != null) 
    { 
     holiday.Id = existingHoliday.Id; 
     ClientContext.Entry(existingHoliday).State = 
        ClientContext.Entry(existingHoliday).State == EntityState.Added  
          ? EntityState.Detached 
          : EntityState.Deleted; 
    }  
    ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Added; 
} 

同樣,我不知道什麼是rootLocation所以你的邏輯可能會有所不同。

作爲進一步的優化,如果假期列表不是太大,你應該將它全部加載到內存中,而不是在每次迭代時調用SingleOrDefault,這將會觸及數據庫。

因此,有隻是一個單一的命中數據庫加載所有的人(同樣,如果沒有太多的記憶不是一個問題),並在客戶端搜索:

var allHolidays = ClientContext.Holidays.ToList();  
foreach (var holiday in clientDataObj.Holidays) 
{ 
    Holiday existingHoliday = 
       allHolidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date)); 
    /* ... */ 
} 

這隻應該點擊數據庫一次查詢

請注意,如果同時使用此方法和上述方法,則需要將新的假期也添加到列表中,以便在Excel導入可能有重複的情況下進行檢查。這在你的問題中沒有涉及到,所以請檢查規格。

+0

謝謝,我會試試看。 – devC

+0

謝謝,你有一些寶貴的建議。 – devC

+0

嗨,我用你的建議解決了問題,但現在有一個新問題。感謝您能否提供幫助。 http://stackoverflow.com/questions/37202341/ef-associated-entity-is-trying-to-add-to-the-database-when-adding-an-entity – devC