2011-12-02 22 views
3

這一個令我絕對瘋狂,尤其是因爲我懷疑要麼有簡單的修復,要麼我要求太多EF ...嘗試使用EntityFramework保存已存儲在ASP.NET控件狀態中的實體

的情況是這樣的:

我有一個用戶控件(ASCX),基本上是作爲一個EF實體編輯表單。當控制數據綁定時,我通過ID從數據庫中提取對象並將其置於控制狀態(通過覆蓋SaveControlState()LoadControlState())。

然後用戶開始進行任何更改或不做什麼的快樂方式。此對象具有導航屬性,因此當他們對導航屬性進行更改時(例如,通過添加位置來收集對象上的位置),我正在更新處於控制狀態的dataItem

最後,在用戶全部完成,並點擊保存按鈕,我嘗試保存或使用下面的代碼創建記錄:

protected void SaveButton_Click(object sender, EventArgs e) 
{ 
    DepartmentLookup dept = Master.DataContext 
     .Departments.Find(ResourceDepartment.SelectedValue.ToInt()); 

    LocationLookup location = dataItem.Locations[ResourceLocation.SelectedIndex]; 
    if (dataItem.OfficeLocation == null) 
    { 
     dataItem.OfficeLocation = new OfficeLocationLookup() 
     { 
      Location = location, 
      OfficeLocationName = location.LocationName 
     }; 
    } 
    else if (!dataItem.OfficeLocation.Location.Equals(location)) 
    { 
     dataItem.OfficeLocation.Location = location; 
     dataItem.OfficeLocation.OfficeLocationName = location.LocationName; 
    } 

    foreach (LocationLookup loc in dataItem.Locations) 
    { 
     if (loc.LocationTypeID == default(int)) 
     { 
      LocationTypeLookup locType = Master.DataContext 
       .LocationTypes.SingleOrDefault(lt => 
        lt.LocationType == loc.LocationType.LocationType); 

      if (locType != null) 
       loc.LocationType = locType; 
     } 
     else 
     { 
      LocationTypeLookup locType = Master.DataContext 
       .LocationTypes.Find(loc.LocationTypeID); 
      if (locType.LocationType != loc.LocationType.LocationType) 
      { 
       LocationTypeLookup newType = new LocationTypeLookup() 
       { 
        LocationType = loc.LocationType.LocationType 
       }; 

       loc.LocationType = newType; 
      } 
     } 
    } 

    dataItem.PrimaryPhone = PrimaryPhone.Text; 
    dataItem.CellPhone = CellPhone.Text; 
    dataItem.Department = dept; 
    dataItem.EmailAddress = EmailAddress.Text; 
    dataItem.LastModifiedBy = HttpContext.Current.User.Identity.Name; 
    dataItem.LastModifiedDtm = DateTime.UtcNow; 

    if (dataItem.ResourceID == default(int)) 
     Master.DataContext.Resources.Add(dataItem); 
    else 
    { 
     DbEntityEntry<Resource> entry = Master.DataContext.Entry<Resource>(dataItem); 
     if (entry != null && entry.State == EntityState.Detached) 
     { 
      Master.DataContext.Resources.Attach(dataItem); 
      // entry.State = EntityState.Modified; 
     } 
    } 

    Master.DataContext.SaveChanges(); 
} 

我已經嘗試了許多不同的方式,試圖挽救該對象到數據庫,所有導致各種錯誤。唯一沒有拋出異常的方法是SetValues方法,它也沒有保存任何導航屬性,因此被證明是沒有價值的。

任何幫助或建議都將非常感謝,因爲我已經在這個問題上花了幾天時間來解決我的大腦問題。

在此先感謝! J

回答

1

當在會話中保存實體對象(而不是控制狀態)時,我遇到了類似的問題。問題是檢索到的對象具有各種不同的ObjectContext,這導致保存失敗。

這取決於您如何管理上下文,但最好的想法是將上下文與Request對象相關聯,並使用工廠類來檢索它,因此每個請求使用一個上下文。

HttpContext.Current.Items["Context"] = context 

任何其他模式導致我很大的問題。

根據我的經驗,由於難以管理上下文,因此將整個實體保存在Session(或ControlState)中並不是一個好主意。即使使用上述(非常安全)模式,上下文也會來自不同的請求。我最終只是將對象ID保存到Session(ControlState)中,並使用包裝類來檢索它們。我堅持要在Request集合中傳遞的對象,而不是通過回發持久化的對象。

這是我很沮喪的question與我在類似領域的鬥爭。希望它有一些用處。

+0

謝謝蒂姆,我實施了你的建議,它解決了一些問題。不幸的是,我仍然有很多似乎與嵌套實體有關的問題。我在考慮這一點,我可能需要重建我的保存方法中的所有實體。你認爲這看起來合理嗎,或者有更好的辦法? – Jason

+0

@typefragger我不得不說,我重建實體。如果我正在進行保存,我會從最低的孩子開始建立實體。我經常把它們一次一個地保存下來。我認爲你可以將整個對象圖傳遞給保存方法,並且它可以爲你工作,但它不能像那樣工作。你必須牢記關係中的實體。我相信這不是最有效的方式,對我來說 –

+0

@typefragger附加實體和導航屬性也存在問題。 objectmanager只告訴你父連接是否被連接 - 不是兒童http://stackoverflow.com/questions/7938728/objectstatemanager-trygetobjectstateentry-returns-false-for-attached-object/7938909#7938909。我也對此感到惋惜 –