2009-10-21 172 views
0

我對我的實體添加功能有點麻煩。Ado實體框架添加數據

設置

爲簡單起見,我在DB有4個表,客戶,地址,面積,位置。

  • 客戶存儲基本客戶詳細信息IE瀏覽器。 ID,名稱,用戶名,密碼等
  • 地址商店街道名稱,街道號碼等
  • 區域商店區域名稱和區號。
  • 位置商店位置名稱和位置代碼。

的關係如下 客戶* ---> 1個地址* ---> 1區* ---> 1地點

在我的應用程序,我想有一個函數來創建一個新客戶。還有一些文本框可用於地址信息。區域和位置信息可以從我從數據庫中預取的可用區域和位置列表中選擇,並填充到組合框中。

我的應用程序不直接使用ADO.net EF,而是通過WCF數據服務調用。該服務位於IIS託管的SQL服務器上。以下是在業務邏輯層檢索客戶的服務電話

/// <summary> 
/// The get all customers. 
/// </summary> 
/// <returns> 
/// </returns> 
public static List<Customer> GetAll() 
{ 
    using (var context = new CustomerDataEntities()) 
    { 
     // I may be missing something here.. Possibly a call to Detach(). 
     // I have been ommitting it because a call to Detach() 
     // tends to cut away any .Include() from the data. Maybe there is another way? 
     return context.CustomerSet.ToList(); 
    } 
} 

正如您所看到的。這將無限期地導致Context的多個實例(如Craig Stuntz所述,這是一個錯誤)。

然後在WCF數據服務中。

// IDataService.cs 
[OperationContract] 
List<Customer> GetAllCustomers(); 

// DataService.svc.cs 
public List<Customer> GetAllCustomers() 
{ 
    return CustomerBLL.GetAll(); 
} 

應用程序繼續使用的客戶列表從以上檢索,而OPS創建一個新的客戶,像這樣:

private Location newLocation; 
private Area newArea; 
private Address newAddress; 
private Customer newCustomer; 

// Code omitted for clarity.. 

public void CreateCustomer() 
{ 
    newLocation = new Location(); 
    newArea = new Area{Location = newLocation}; 
    newAddress = new Address{Area = newArea}; 
    newCustomer = new Customer{Address = newAddress}; 
} 

凡位置,面積,地址和客戶是參考ADO.net EF模​​型類。然後到newLocation和newArea被修改,當用戶在ComboBox選擇從一個列表中的位置或區域,像這樣:

private Location _selectedLocation; 
public Location SelectedLocation 
{ 
    get { return _selectedLocation; } 
    set { 
      _selectedLocation = value; 
      newLocation = _selectedLocation; 
     } 
} 

SelectedLocation是綁定到位置組合框的組合框的SelectedItem數據。 newArea發生類似的過程。

當用戶點擊保存會發生以下情況:

public bool SaveCustomer(Customer customer) 
{ 
    if(customer == null) return false; 

    var dataService = new DataService.DataServiceClient(); 
    try 
    { 
     if (customer.ID > 0) dataService.UpdateCustomer(customer); 
     else dataService.CreateCustomer(customer); 
    } 
    catch (Exception e) 
    { 
     Trace.WriteLine(e.Message); 
     return false; 
    } 

    return true; 
} 

被調用的數據服務是像這樣的方法。

/// <summary> 
/// The create. 
/// </summary> 
/// <param name="customer"> 
/// The customer. 
/// </param> 
public static bool Create(Customer customer) 
{ 
    if (customer== null) return false; 

    // Once again, a new instance of the Context.. 
    using (var context = new CustomerDataEntities()) 
    { 
     try 
     { 
      context.AddToCustomerSet(customer); 
      context.SaveChanges(); 
     } 
     catch (Exception e) 
     { 
      return false; 
     } 

     return true; 
    } 
} 

的問題

這將引發錯誤:

The object cannot be added to the ObjectStateManager because it already has an EntityKey. Use ObjectContext.Attach to attach an object that has an existing key.

這是因爲Customer.Address.Area的背景下,已經存在,並且其要求我使用context.Attach()第一。我試過context.Attach()無濟於事。我應該採取什麼方法來解決這個問題?

+0

請編輯您的問題,包括確切的錯誤信息。我懷疑你使用了兩種不同的上下文,這通常是一個錯誤。 – 2009-10-21 13:01:12

+0

克雷格,我確實使用了多種不同的上下文。這是因爲我通過WCF數據服務訪問數據。我已經用更多的細節編輯了這個問題,所以你可以看到我出錯的地方。 PS。我對ADO.net EF非常感興趣,所以感謝您的耐心等待。 – 2009-10-21 23:04:20

回答

1

與其試圖針對這個問題的具體解決方案,我會敦促您爲ObjectContexts的生命週期提出一個通用策略。我不能給你一個這樣的「最佳實踐」,因爲它取決於你的應用程序。例如,我主要做ASP.NET MVC應用程序,所以我的ObjectContexts的生命週期始終是一個持續一個請求的上下文。

這裏的一般問題是,實體框架會期望對象圖中的任何對象(換句話說,直接或直接相互引用的對象)將成爲單個ObjectContext的一部分。如果,例如,您有一個稱爲區域的對象,其連接到某個ObjectContext的和不附加任何ObjectContext的(換句話說,它是分離的)一個對象調用的客戶,並更改客戶,使其間接指通過地址的區域,然後如果你看看客戶的EntityState,你會看到它現在被「添加」了。試圖通過AddToCustomerSet將其添加到不同的ObjectContext將會拋出您報告的錯誤,因爲實體不能存在於兩個ObjectContext中。另一方面,在前一個上下文中調用SaveChanges將導致客戶被添加到數據庫中,而根本不調用AddToCustomerSet,因爲它已隱式添加到集合中。

這可能聽起來很複雜,或難以管理。但是你會發現,如果你能找到一種方法來使用一個ObjectContext,幾乎所有的複雜事件都會消失。沒有規則禁止使用多個ObjectContext,但是如果您是Entity Framework的新手,我會敦促您在稍後使用EF的時候不要這樣做。

+0

再次感謝克雷格,這絕對是我需要的那種方向。我也從CodeProject http://www.codeproject.com/KB/architecture/attachobjectgraph.aspx找到了這個問題的解決方案。這解決了嘗試使用混用的Attached和Detached對象相互引用來添加/修改數據的問題。 – 2009-10-22 23:08:09